Robust Scripts
Reading Lines
Preserving Text
Line-oriented scripts need to keep the text exactly as it arrives. IFS= read -r is the usual safe loop shape.
Program
Play the script to watch two input lines update the loop variables without losing the embedded space.
read_lines.sh
Replay: real traced execution (multi-file project)
#!/usr/bin/env bash
count=0
last=""
while IFS= read -r line; do
count=$((count + 1))
last="$line"
done <<'DATA'
alpha
two words
DATA
echo "$count:$last"
count ← 0
3count=04last=""values this step0countlast ← (empty)
3count=04last=""5while IFS= read -r line; dovalues this step(empty)lastline ← alpha
4last=""5while IFS= read -r line; do6 count=$((count + 1))values this stepalphalinecount ← 1
5while IFS= read -r line; do6 count=$((count + 1))7 last="$line"values this step0 → 1countlast ← alpha
6 count=$((count + 1))7 last="$line"8done <<'DATA'values this stepalphalastalphalineline ← two words
4last=""5while IFS= read -r line; do6 count=$((count + 1))values this steptwo wordslinecount ← 2
5while IFS= read -r line; do6 count=$((count + 1))7 last="$line"values this step1 → 2countlast ← two words
6 count=$((count + 1))7 last="$line"8done <<'DATA'values this steptwo wordslasttwo wordslineecho "$count:$last"
11DATA12echo "$count:$last"output2:two wordsvalues this step2counttwo wordslast
Follow the Lines
countstarts at0, andlaststarts empty.- The first input line is
alpha, socount=1andlast=alpha. - The second input line is
two words. - The loop keeps the embedded space, so
last="two words". - The script prints
2:two words. | input line | count after read | last after read | | --- | --- | --- | | alpha | 1 | alpha | | two words | 2 | two words | | stdout | 2 |two words|
read -r
`read -r` reads a line without treating backslashes as escape characters.
IFS=
`IFS=` keeps leading and trailing whitespace from being trimmed before assignment.
here document
`<<'DATA'` feeds literal lines to the loop until the closing marker.
Exercise: read_lines.sh
Reproduce 2:two words, then trace which line becomes the final last value.