Step 1 of 5 · Reading · ~2 min
Learn
Control Flow
Loops
Bash loops iterate over the things shells care about: words, lines, files, and number ranges. The syntax is small; the skill is choosing what to feed the loop — and one famous trap when the input is lines rather than words.
for: over a list of words
for fruit in apple banana cherry; do
echo "I like $fruit"
done
for x in LIST walks whatever words follow in — and those words usually come from an expansion:
for f in *.txt; do # glob: every .txt file, safely (spaces intact!)
echo "processing $f"
done
for i in {1..5}; do # brace expansion: 1 2 3 4 5
echo "$i"
done
for i in $(seq 1 "$n"); do # seq when the bound is a VARIABLE ({1..$n} does NOT expand)
…
done
That last comment earns its place: brace ranges are expanded before variables are substituted, so {1..$n} is the literal string {1..$n} — a classic gotcha. Variable bounds want seq or the C-style form:
for (( i = 1; i <= n; i++ )); do # C-style, arithmetic context rules apply
total=$(( total + i ))
done
while: conditions and — crucially — lines
while (( n > 1 )); do
…
done
…but while's real day job in bash is reading input line by line:
while read -r line; do
echo "got: $line"
done
This loop consumes stdin until it runs out — the pattern for processing files and piped data (-r stops backslash-mangling; write it always). It matters because the alternative people invent — for line in $(cat file) — is wrong: unquoted expansion splits on all whitespace, so lines with spaces shatter into words. Lines want while read -r; words want for. Carve that distinction in; it's the difference between a script that works and one that works on your test file.
break and continue behave as everywhere. Infinite loops are while true; do … done — true being, in the spirit of last lesson, just a command that always succeeds.
Your exercise: Sum 1 to N
Read n, add up 1 through n, print the total. The starter gives you the read and the accumulator's starting value; the loop is yours.
Three graded details are the same in every track: initialise before the loop, use <= rather than < so N itself is included, and print once after the loop rather than inside it. Two are bash's own. Do not reach for {1..$n} -- you now know why it silently fails, and the C-style for (( )) shown above takes a variable bound natively. And accumulate with an arithmetic expansion: sum+=i outside an arithmetic context is string append, which is exactly how one real submission ended up printing 0iiiii.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…