diff --git a/SC2013.md b/SC2013.md new file mode 100644 index 0000000..bd8bae8 --- /dev/null +++ b/SC2013.md @@ -0,0 +1,50 @@ +# To read lines rather than words, pipe/redirect to a 'while read' loop. + +### Problematic code: + + for line in $(cat file | grep -v '^ *#') + do + echo "Line: $line" + done + +### Correct code: + + grep -v '^ *#' < file | while IFS= read -r line + do + echo "Line: $line" + done + +or without a subshell (bash, zsh, ksh): + + while IFS= read -r line + do + echo "Line: $line" + done < <(grep -v '^ *#' < file) + +### Rationale: + +For loops by default (subject to `$IFS`) read word by word. Additionally, glob expansion will occur. + +Given this text file: + + foo * + bar + +The for loop will print: + + Line: foo + Line: aardwark.jpg + Line: bullfrog.jpg + ... + +The while loop will print: + + Line: foo * + Line: bar + + +### Contraindications + +If you want to read word by word, you should still use a while read loop (e.g. with `read -a` to read words into an array). + +Rare reasons for ignoring this message is if you don't care because your file only contains numbers and you're not interested in good practices, or if you've set `$IFS` appropriately and also disabled globbing. \ No newline at end of file