Skip to content
Arrays
step 1/5

Reading — step 1 of 5

Learn

~2 min readArrays and Scripts

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…