06 Text Processing

Learning objectives

  • Sort, deduplicate, and count text.
  • Extract fields by delimiter.
  • Perform simple text replacement and batch processing.

Command overview

CommandPurposeMeaningBasic usageExample
sortSort text linesSorts lexically or numericallysort filesort names.txt
uniqRemove adjacent duplicate linesShort for unique; usually used with sortuniq filesort names.txt | uniq
cutExtract text columnsSelects fields by character position or delimitercut [options] filecut -d ":" -f 1 /etc/passwd
awkAnalyze text and process columnsSuitable for field-oriented text processingawk 'rules' fileawk '{print $1}' app.log
sedStream text editorCommonly replaces, removes, or prints linessed 'expression' filesed 's/old/new/g' file.txt
trTranslate or delete charactersPerforms character-level transformationstr 'old_chars' 'new_chars'printf '%s\n' abc | tr '[:lower:]' '[:upper:]'
xargsTurn NUL-delimited input into argumentsOrdinary newlines cannot represent every legal filename; on GNU/Linux use with -print0/-0find ... -print0 | xargs -0 commandfind . -type f -name '*.log' -print0 | xargs -0 -- wc -l

Common scenarios

Sort and deduplicate:

sort names.txt | uniq
sort names.txt | uniq -c

Extract the first field of a colon-separated file:

cut -d ":" -f 1 /etc/passwd

Extract the first log field:

awk '{print $1}' app.log

Replace text in output:

sed 's/error/ERROR/g' app.log

Turn lowercase into uppercase:

printf '%s\n' 'linux' | LC_ALL=C tr '[:lower:]' '[:upper:]'

Pass found files safely to another command:

find . -type f -name '*.log' -exec wc -l -- {} +
find . -type f -name '*.log' -print0 | xargs -0 -- wc -l

Notes for beginners

  • uniq removes only adjacent duplicate lines, so use sort before uniq in the usual case.
  • sed 's/old/new/g' file prints a transformed result by default; it does not modify the source file.
  • sed -i is not POSIX. GNU and BSD/macOS differ on -i and backup-suffix syntax. This course first writes to a new file and compares it instead of editing in place.
  • awk splits fields on whitespace by default; $1 is the first field and $2 is the second.
  • An ordinary newline pipeline cannot safely represent every legal filename. The portable first choice is find -exec ... {} +; GNU/Linux can use -print0 | xargs -0.
  • Sorting, case conversion, and character classes depend on locale. Set LC_ALL=C explicitly when reproducible byte order is required.

Replacement exercise without overwriting a source file

sed 's/error/ERROR/g' -- app.log > app.log.new
cmp --silent -- app.log app.log.new
cmp_rc=$?
printf 'content_changed=%s\n' "$cmp_rc"

Inspect app.log.new first, then decide whether to replace the original with a controlled mv. Do not redirect output back into the input file.

Mastery check

  • I can explain why uniq usually requires sorted input.
  • I can handle filenames containing spaces and newlines without bare find | xargs.
  • I know that sed in-place editing and locales have platform differences.

References