====== Text Processing Recipes ======
grep / sed / awk / jq / sort / cut / find / xargs: the stuff that answers
"how do I..." faster than writing a script.
Deep dives: [[terminal:scripting:sed|sed]] · [[terminal:scripting:awk|awk]] · [[terminal:scripting:grep|grep]] ·
[[terminal:scripting:jq|jq]] · [[terminal:scripting:find_xargs|find-xargs]] · [[terminal:scripting:curl|curl]] ·
[[terminal:scripting:regex|regex]] (which flavor each tool uses)
===== find + xargs =====
find . -name '*.log' -mtime +7 -delete # old logs
find . -type f -size +100M # big files
find . -name '*.txt' -print0 | xargs -0 grep -l foo # safe for spaces
find . -newer marker.txt # changed since file
find . -type f -exec chmod 644 {} + # bulk chmod (+ = batched)
===== grep / rg =====
sudo apt install ripgrep # rg is faster and simpler than grep -r
rg -n 'pattern' # recursive, line numbers, respects .gitignore
rg -l --type-add 'conf:*.conf' -tconf 'listen' # file-type filter
rg -A3 -B2 'error' log # context
grep -vE '^\s*(#|$)' file # strip comments+blank lines
===== sed =====
sed -i 's/old/new/g' file # in-place
sed -i.bak 's/x/y/' file # with backup
sed -n '10,20p' file # lines 10-20
sed -n '/START/,/END/p' file # range by pattern
sed 's/^/ /' file # indent
sed '/^$/d' file # delete blank lines
===== awk =====
awk '{print $1}' # column 1
awk -F: '{print $1}' /etc/passwd # custom delimiter
awk '$3 > 100 {print $1}' # condition
awk '{s+=$1} END {print s}' # sum a column
awk '!seen[$0]++' # dedupe, keep order
awk 'NR==5' file # just line 5
df -h | awk '$5+0 > 80 {print}' # numeric compare
===== jq =====
sudo apt install jq
jq . file.json # pretty-print
jq '.items[].name' # nested field
jq -r '.items[] | "\(.name) \(.size)"' # raw strings, format
jq 'keys' # object keys
jq 'length' # array length
jq '.[] | select(.age > 30)' # filter
jq -s 'add' *.json # slurp files into one array
curl -s api | jq '.data' # from a pipe
===== sort / uniq / comm =====
sort -h du_output # human sizes
sort -k2 -n # numeric by column 2
sort -u file # sort+dedupe
sort file | uniq -c | sort -rn | head # frequency top
comm -12 <(sort a) <(sort b) # lines in both
diff -u <(cmd1) <(cmd2) # diff two commands' output
===== cut / paste / tr / column =====
cut -d: -f1,3 /etc/passwd
echo "a b c" | tr ' ' '\n' # words to lines
tr 'a-z' 'A-Z' < f # uppercase
column -t -s, file.csv # align columns
paste -d, a.txt b.txt # join lines side by side
===== Miscellaneous greats =====
wc -l file # count lines tee -a out.log # write+show
xargs -I{} cp {} dest/ # template per item
xargs -P4 -n1 cmd # parallel, one arg each
comm/tabular viewing: less -S # no wrap, scroll right
head -n -5 file # all but last 5 lines
tac file | less # reverse order
===== CSV without a real CSV parser =====
''mlr'' (miller) or ''csvkit'' (''sudo apt install miller csvkit''): proper CSV
tools that handle quoted commas, unlike ''cut -d,'':
mlr --csv cut -f name,age in.csv
csvcut -n in.csv && csvcut -c 2 in.csv | csvlook
===== See Also =====
* [[terminal:scripting:start|Scripting Index]]
* [[terminal:tools:start|CLI Tools]]
* [[terminal:start|Return to terminal]]
* [[start|Return to wiki home]]