# Bash I/O, Pipelines, and Data Processing ## Built-ins vs External Commands - Prefer Bash built-ins for light text processing and arithmetic. - Use external commands (`sed`, `awk`, `grep`, `cut`, `tr`, `bc`) for heavy or complex text processing. ```bash # Prefer built-in addition=$(( X + Y )) # Prefer external for sophisticated transforms substitution="$(echo "$string" | sed -e 's/^foo/bar/')" ``` ## Process Substitution Use `<(command)` and `>(command)` for treating command output as a file. ```bash diff -u <(sort file1) <(sort file2) tar cjf >(bzip2 -c > file.tar.bz2) foo ``` ## `while read` with Process Substitution When iterating over command output and modifying variables in the parent shell, use process substitution as the input source rather than piping into `while`. A pipe creates a subshell, so variable changes are lost. ```bash # Good: changes to $count survive local -i count=0 while IFS='' read -r line; do (( count++ )) done < <(command) # Bad: $count is lost because the while runs in a subshell local -i count=0 command | while IFS='' read -r line; do (( count++ )) done ``` ### `IFS='' read -r line` for exact line preservation Use `IFS='' read -r line` when reading lines you intend to preserve exactly, including leading and trailing whitespace. Without `IFS=''`, leading/trailing whitespace is stripped; without `-r`, backslashes are interpreted. ```bash while IFS='' read -r line; do echo "$line" done < file.txt ``` ## Here-Documents and Here-Strings Use here-docs and here-strings for multi-line or inline input. ```bash # Here-document with variable interpolation cat </dev/null`, `1>&2`). - Remember redirection order matters. ```bash echo Foo 2>/dev/null 1>&2 # suppresses everything ``` ## `/dev/tcp` Networking Bash supports TCP via pseudo-files: ```bash cat < /dev/tcp/time.nist.gov/13 exec 5<>/dev/tcp/google.de/80 ``` ## List Processing: Pipes over Arrays For simple list processing, prefer pipelines over arrays. Pass data through stdout to the next stage and use stderr for logging. ```bash main () { filter_lines | process_lines | postprocess_lines | generate_report } ``` ## Reading Files and Arrays - **Read a whole file into a variable** without spawning `cat`: `cfg=$(