Reading — step 1 of 5
Learn
Arrays
Bash arrays are the language's late admission that word-splitting wasn't a data structure. They hold real lists — elements with spaces, empty elements, the works — if you use the (admittedly baroque) syntax exactly. The payoff: correct handling of filenames and arguments, the two lists every script actually manages.
The syntax, precisely
fruits=("apple" "kiwi fruit" "cherry") # literal — note element 2 contains a space
fruits+=("mango") # append
echo "${fruits[0]}" # apple — index from 0, braces REQUIRED
echo "${#fruits[@]}" # 4 — length
Braces are non-negotiable: $fruits[0] without them means "$fruits then the literal text [0]" (bash expands $fruits as element 0 — a trap that almost works, the worst kind).
The one expansion to memorize: "${arr[@]}"
for f in "${fruits[@]}"; do
echo "-> $f"
done
Output — four lines, "kiwi fruit" intact. That quoted-[@] form is the entire reason arrays exist: it expands to one word per element, boundaries preserved, no matter what the elements contain. Every variation loses:
${fruits[@]}unquoted → word-splits: "kiwi fruit" becomes two items"${fruits[*]}"→ ONE word containing everything, space-joined
So: iterating, passing to commands, forwarding — always "${arr[@]}". (Its twin for script arguments is "$@", same semantics, which is why the Functions lesson called it the only correct forwarding form.)
Filling arrays from data
read -r -a nums # split ONE input line into an array
mapfile -t lines # slurp ALL of stdin, one element per LINE
files=(*.txt) # glob straight into an array — spaces safe
read -a for a line of fields, mapfile -t for lines (the -t trims newlines), glob-into-array for files. These three cover effectively every "get a list into bash" situation — and each replaces a word-splitting hack that breaks on real data.
Iterating with indices, when you must
for i in "${!nums[@]}"; do # ${!arr[@]} = the list of indices
echo "$i: ${nums[$i]}"
done
Rarely needed (element iteration covers most work), but ${!arr[@]} is the piece people can't find when they need position numbers.
Your exercise: Largest Number
Read numbers, print the biggest — the tracker pattern with an array intake. If input is one line of numbers:
read -r -a nums
best=${nums[0]}
for n in "${nums[@]}"; do
if (( n > best )); then
best=$n
fi
done
echo "$best"
If input is one number per line, swap the intake to mapfile -t nums — same loop (check the exercise's examples; you know this drill by now). Graded essentials, all old friends wearing brackets: seed best from a real element (all-negative input lurks), (( )) for the numeric comparison, and the quoted "${nums[@]}" doing the load-bearing work of keeping your list a list.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…