| name | text-processing |
| description | > Use when this capability is needed. |
Text Processing
Before running commands, detect the OS and load the matching reference for
platform-specific syntax and gotchas:
- Linux —
references/linux.md (GNU sed/awk/sort with extended flags)
- macOS —
references/macos.md (BSD sed/awk/sort, Homebrew GNU alternatives)
- Windows —
references/windows.md (PowerShell: Select-String, Import-Csv, ForEach-Object)
OS detection:
uname -s 2>/dev/null || echo Windows
Key platform difference: sed -i syntax varies — check the OS reference before in-place edits.
Quick Reference
| Task | Portable command |
|---|
| Find and replace (stdout) | sed 's/old/new/g' file |
| Extract column | awk '{print $2}' file |
| Cut field (delimited) | cut -d',' -f2 file |
| Sort lines | sort file |
| Unique lines | sort file | uniq |
| Count lines/words/chars | wc -lwc file |
| Translate characters | tr 'a-z' 'A-Z' < file |
| First N lines | head -n 10 file |
| Last N lines | tail -n 10 file |
sed — Stream Editor
Substitution (portable)
sed 's/foo/bar/' file.txt
sed 's/foo/bar/g' file.txt
sed 's|/usr/local|/opt|g' file.txt
sed '5s/foo/bar/g' file.txt
sed '10,20s/foo/bar/g' file.txt
sed '/pattern/s/foo/bar/g' file.txt
sed -E 's/([a-z]+)_([a-z]+)/\2_\1/g' file.txt
sed 's/\(.*\)=\(.*\)/\2=\1/' file.txt
Deletion (portable)
sed '/pattern/d' file.txt
sed '5d' file.txt
sed '10,20d' file.txt
sed '/^$/d' file.txt
sed '/pattern/!d' file.txt
Print and Extract (portable)
sed -n '/pattern/p' file.txt
sed -n '10,20p' file.txt
sed -n '/pattern/=' file.txt
Common Transforms (portable)
sed 's/[[:space:]]*$//' file.txt
sed 's/^[[:space:]]*//' file.txt
sed 's/\r$//' file.txt
sed -e 's/foo/bar/g' -e 's/baz/qux/g' file.txt
awk — Pattern Scanning and Processing
Field Extraction
awk '{print $1}' file.txt
awk '{print $NF}' file.txt
awk -F',' '{print $2}' data.csv
awk -F'\t' '{print $1}' data.tsv
awk -F',' -v OFS='\t' '{print $1, $2}' data.csv
Pattern Matching
awk '/error/' log.txt
awk '!/comment/' file.txt
awk '$3 > 100' data.txt
awk '$1 == "Alice"' data.txt
awk '$2 ~ /^admin/' users.txt
awk '/START/,/END/' file.txt
awk 'NR >= 10 && NR <= 20' file.txt
Calculations and Aggregation
awk '{sum += $2} END {print sum}' data.txt
awk '{sum += $2; n++} END {print sum/n}' data.txt
awk 'NR==1 || $2 > max {max=$2} END {print max}' data.txt
awk '$3 > 100 {count++} END {print count}' data.txt
awk '{count[$1]++} END {for (k in count) print k, count[k]}' data.txt
awk '{sum[$1] += $2} END {for (k in sum) print k, sum[k]}' data.txt
String Operations
awk '{print length($1), $1}' file.txt
awk '{print substr($0, 1, 10)}' file.txt
awk '{print toupper($1)}' file.txt
awk '{print tolower($1)}' file.txt
awk '{gsub(/old/, "new"); print}' file.txt
awk '{printf "%-20s %10.2f\n", $1, $2}' data.txt
Built-in Variables
| Variable | Meaning |
|---|
NR | Current line number (across all files) |
NF | Number of fields in current line |
FS / OFS | Input / output field separator |
RS / ORS | Input / output record separator |
FILENAME | Current filename |
FNR | Line number within current file |
BEGIN and END
awk 'BEGIN {FS=","; OFS="\t"} {$1=$1; print}' data.csv
awk 'BEGIN {print "Name\tScore"} {print $1 "\t" $2} END {print "Done"}' data.txt
sort (portable flags)
sort file.txt
sort -r file.txt
sort -n file.txt
sort -k2 file.txt
sort -k2,2 file.txt
sort -t',' -k3 -n data.csv
sort -f file.txt
sort -u file.txt
sort -s -k2 file.txt
sort -k1,1 -k2,2n file.txt
sort -c file.txt
uniq (requires sorted input)
sort file.txt | uniq
sort file.txt | uniq -c
sort file.txt | uniq -d
sort file.txt | uniq -u
sort file.txt | uniq -c | sort -rn | head -10
cut
cut -d',' -f1 data.csv
cut -d',' -f1,3 data.csv
cut -d',' -f2-4 data.csv
cut -c1-10 file.txt
cut -c5- file.txt
tr — Translate Characters
tr 'a-z' 'A-Z' < file.txt
tr 'A-Z' 'a-z' < file.txt
tr ':' '\t' < file.txt
tr -d '0-9' < file.txt
tr -d '\r' < file.txt
tr -s ' ' < file.txt
tr '[:lower:]' '[:upper:]' < file.txt
wc — Word Count
wc file.txt
wc -l file.txt
wc -w file.txt
wc -m file.txt
wc -c file.txt
Common Pipelines
tr -s ' ' '\n' < file.txt | sort | uniq -c | sort -rn | head -10
awk -F',' '{print $2}' data.csv | sort | uniq -c | sort -rn
awk '!seen[$0]++' file.txt
paste -s -d+ numbers.txt | bc
grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' file.txt | sort -u
awk '{print $4}' access.log | cut -d: -f1,2 | sort | uniq -c | sort -rn
Important Notes
sed -i syntax differs by OS — always check the platform reference before in-place edits
- Use
-E for extended regex in sed (portable across GNU and BSD)
uniq only removes adjacent duplicates — always sort first
awk field numbering starts at $1; $0 is the entire line
cut cannot reorder fields — use awk for that
tr operates on characters, not strings — use sed for string replacement
- For large files,
awk is generally faster than multiple piped commands
sort -n treats fields as numbers; without -n, "9" sorts after "10" (lexicographic)
- When processing binary files, use
LC_ALL=C to avoid locale issues
Source: bug-ops/zeph — distributed by TomeVault.