Text Processing
The core command-line tools for searching, transforming, and extracting text - grep, sed, awk, cut, sort, and uniq - and how they combine into pipelines that do more than any one of them alone.
Most day-to-day Linux administration comes down to text: log lines, config files, command output. These tools are what turn a wall of text into just the part you need - see Globbing and Regex for the pattern syntax they share, and Pipes and Redirection for how they chain together.
grep: finding lines that match
grep "error" app.log # lines containing "error"
grep -i "error" app.log # case-insensitive
grep -v "debug" app.log # invert: lines NOT containing "debug"
grep -c "error" app.log # count matching lines, don't print them
grep -n "error" app.log # show line numbers
grep -r "TODO" src/ # recurse into a directory
grep -A 3 -B 1 "panic" app.log # 3 lines after, 1 line before each match
-E switches to extended regex (equivalent to egrep); without it,
grep uses basic regex, where +, ?, and | need escaping.
sed: stream editor for substitution
sed reads input line by line and applies an editing command to each,
most commonly a find-and-replace:
sed 's/foo/bar/' file.txt # replace first "foo" per line with "bar"
sed 's/foo/bar/g' file.txt # replace every occurrence per line
sed -i 's/foo/bar/g' file.txt # edit the file in place
sed -i.bak 's/foo/bar/g' file.txt # in place, keeping a .bak backup first
sed -n '10,20p' file.txt # print only lines 10-20
sed '/^#/d' file.txt # delete lines starting with #
-i with no argument overwrites the file with no backup - on systems
where that matters, always test a sed command without -i first to
see what it would do before committing to it.
awk: field-based processing
awk splits each input line into fields (whitespace-delimited by
default) and lets you act on specific ones - it's a small programming
language, but most real-world use is one-liners:
awk '{print $1}' access.log # print just the first field
awk -F: '{print $1}' /etc/passwd # use : as the field separator
awk '{print $NF}' file.txt # print the last field ($NF = field count)
awk '$3 > 100 {print $1, $3}' data.txt # print fields 1 and 3 where field 3 > 100
awk '{sum += $2} END {print sum}' data.txt # sum a column
ps aux --sort=-%mem | awk '{print $4, $11}' | head -5
%MEM COMMAND
8.2 /usr/lib/firefox/firefox
3.1 /usr/bin/gnome-shell
cut, sort, and uniq: smaller, focused tools
Not everything needs awk's full field logic:
cut -d: -f1 /etc/passwd # field 1, splitting on :
cut -c1-10 file.txt # characters 1 through 10 of each line
sort file.txt # alphabetical
sort -n file.txt # numeric (alphabetical sort orders "10" before "2")
sort -r file.txt # reverse
sort -k2 -n data.txt # sort by the 2nd whitespace-delimited field, numerically
uniq file.txt # remove adjacent duplicate lines (input must be sorted first)
sort file.txt | uniq -c # count occurrences of each unique line
sort file.txt | uniq -c | sort -rn # ...sorted by count, most frequent first
uniq only collapses adjacent duplicates, which is why it's almost
always paired with sort first.
wc: counting
wc -l file.txt # line count
wc -w file.txt # word count
wc -c file.txt # byte count
grep -c "error" app.log # often clearer than `grep "error" app.log | wc -l`
Putting it together
The real value is chaining these into a pipeline, each tool doing one narrow job:
cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
Reads as: extract the first field (client IP) from every line, then find the 10 most frequent values - a quick way to answer "who's hitting this server the most" without writing a dedicated script.