Processing files line by line and embedding templates are bread-and-butter scripting tasks.
read reads one line from stdin into variables. Always use read -r (otherwise backslashes are eaten), and set IFS for the field separator: with IFS=: read -r a b c, the line is split at colons and the last variable gets the rest of the line.
The canonical loop for processing a file line by line is:
while IFS= read -r line; do ...; done < fileIFS= keeps leading and trailing whitespace, -r keeps backslashes, and the redirection after done feeds the whole loop. If the last line has no trailing newline, add || [[ -n $line ]] to the condition to still process it. Use _ as a throwaway variable for fields you skip.
Other useful flags: -p "prompt" shows a prompt, -s hides typing (passwords), -t 5 times out, -a arr reads words into an array.
A here-document passes inline text as stdin: cat <<EOF ... EOF. Variables and $( ) expand inside unless the delimiter is quoted (<<'EOF'), which makes it literal: ideal for generating config files or scripts. <<-EOF strips leading tabs so you can indent the block. A here-string <<< "$var" feeds a single string, handy for read and bc.
Example
cd "$(mktemp -d)"
printf 'alice 30\nbob 25\n' > people.txt
while read -r name age; do
echo "$name is $age"
done < people.txt # alice is 30 / bob is 25
IFS=: read -r user _ uid _ < /etc/passwd
echo "$user has uid $uid" # root has uid 0
read -r first rest <<< "one two three"
echo "$first | $rest" # one | two three
who=World
cat <<EOF
Hello $who, today is $(date +%A)
EOF
cat <<'EOF'
No $expansion here
EOF
# read -rsp "Password: " pw # interactive: hidden inputRemember
- while IFS= read -r line; do ...; done < file is the line loop
- The last variable of read collects the rest of the line
- <<EOF expands variables, <<'EOF' is literal, <<< feeds one string
Watch out for
- Piping into
while readand expecting variables set in the loop to survive; the loop runs in a subshell.