Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Text Processing  ›  Lesson

sort, uniq and tr — Ordering, Counting and Changing Characters

sort 15 minsort orders lines, uniq merges only adjacent duplicates so it follows sort, uniq -c counts them, and tr translates, squeezes or deletes characters from stdin.

sort, uniq and tr — Ordering, Counting and Changing Characters

"Which crop did we pick most often?" is one of the most common questions you can ask about data. It turns out to be a single line of shell: slice out a column, put it in order, count the repeats, and put the counts in order. tr joins them as a tool for tidying text one character at a time.

The rule

sort before uniq, always.

sort puts lines in order. By default it sorts alphabetically, and a few options change that:

Option Does
-n numeric order, so 10 comes after 9
-r reverse the order
-t, fields are separated by commas
-k3 sort starting from field 3
-u keep only one of each identical line
$ tail -n +2 harvest.csv | sort -t, -k3 -n | head -n 1
2026-06-01,basil,0.4,ravi

That line finds the smallest pick: skip the header, sort by kilograms numerically, and keep the first line.

uniq removes duplicate lines, but only when they are next to each other. That's why it nearly always comes after sort. uniq -c puts a count in front of each line:

$ tail -n +2 harvest.csv | cut -d, -f2 | sort | uniq -c
      2 basil
      1 chilli
      3 tomato

tr (translate) changes or deletes characters. It only reads stdin, so you feed it through a pipe or with <:

$ echo tomato | tr a-z A-Z          # TOMATO
$ echo "kg   3.5" | tr -s ' '       # squeeze repeated spaces: kg 3.5
$ tr -d '\r' < windows.csv > unix.csv   # delete Windows carriage returns
$ tr ',' '\t' < harvest.csv         # commas become tabs

Two tab-tidying cousins: expand turns tabs into spaces, and unexpand turns runs of spaces back into tabs.

The shortcut

"How many of each, most first?" always has the same four stages: slice, sort, count, sort again. That's cut, then sort, then uniq -c, then sort -rn.

Which crop did the club pick most often?Step 1 of 4
  1. Slice

    tail -n +2 harvest.csv piped into cut -d, -f2 gives just the crop names.

The trap is running uniq -c on unsorted input. The crops arrive as tomato, basil, tomato, chilli, tomato, basil, and no two neighbours are the same, so every count comes out as 1.

Drills

Answer fast — trust the rule.

quick drill

Why do you almost always run sort before uniq?

quick drill

A file holds the lines 9, 10 and 100. What does plain sort output?

quick drill

Which command turns basil into BASIL?

quick drill

How many lines does the four-stage pipeline print, from tail -n +2 harvest.csv through cut -d, -f4, sort and uniq -c?

Remember

  • sort before uniq, always, because uniq only merges repeats that sit next to each other.
  • "How many of each" means slice, sort, count, sort again: cut, sort, uniq -c, sort -rn.
  • Use sort -n for numbers, and remember that tr only reads stdin.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainThe most common crop

Build the pipeline that shows which crop was picked most often in harvest.csv, explain each stage, and explain why leaving out the first sort gives wrong counts.