Section 1 of 10

1 Before you start

Before you begin, take a few minutes to check what you already know and how confident you feel. You will see the same questions again at the end of the module — this helps both you and us measure what you have learned. Click an option for every question and confidence rating, then click Next to continue.

Pre-test

Which command counts how many lines in diagnoses.csv contain the code I10?

Pre-test

Which cut command extracts the SECOND column of a comma-separated file?

Pre-test

Which pipeline counts how often each value in column 1 of votes.txt appears?

Pre-test

Why does uniq usually need sort in front of it?

Pre-test

Which command converts all lowercase letters in a file to uppercase?

Pre-test

Which grep flag makes the search ignore upper/lower case?

Pre-test

What does grep -v error log.txt print?

Pre-test

Which command sorts numbers in true numeric order (so 10 comes after 9)?

Pre-confidence

I can use grep to find lines matching a pattern and count how many there are.

Not at all confident
Fully confident
Pre-confidence

I can extract a single column from a CSV with cut.

Not at all confident
Fully confident
Pre-confidence

I can combine sort | uniq -c to count how often each unique value appears.

Not at all confident
Fully confident
Section 2 of 10

2 Introduction

Most of what you will do at a Linux terminal is text wrangling - finding lines, picking columns, sorting, counting. These five commands are the workhorses. Each does one tiny job; the magic happens when you chain them with pipes. By the end, the question "how do I extract X from this file?" will have an obvious shape: pick a tool per stage, glue with |.

  • grep - find lines that match a pattern.
  • cut - pick columns or character ranges from each line.
  • sort - sort lines alphabetically or numerically.
  • uniq - squash adjacent duplicate lines (often paired with sort).
  • tr - translate or delete individual characters.
Most terminal text work is just choosing a few single-purpose commands and joining them left to right with the pipe, so each tool does one tiny job on the stream and hands the result to the next.
Most terminal text work is just choosing a few single-purpose commands and joining them left to right with the pipe, so each tool does one tiny job on the stream and hands the result to the next.
Section 3 of 10

3 grep - Find Lines That Match

grep prints every line of its input that contains a given pattern. Simplest form: grep PATTERN FILE.

$ grep P-002 diagnoses.csv
P-002,61,M,172,88,152,95
grep walks a file one line at a time and prints back every line that contains your pattern, discarding all the rest.
grep walks a file one line at a time and prints back every line that contains your pattern, discarding all the rest.

Here are some useful flags that can make grep more useful.

  • -i - case insensitive ("hypertension" or "Hypertension" both match).
  • -v - INVERT - show lines that do NOT match.
  • -c - just count matching lines.
  • -n - prefix each match with its line number.
  • -r - recursive: search every file under a folder.
  • -l - list only the FILENAMES that have a match.
  • -w - whole word match (so "F" does not match "Female").
  • -E - extended regular expressions (alternation with |, +, etc.).
A flag does not merely refine a grep search, it redefines what counts as a match, so the very same pattern can return more lines, fewer lines, or precisely the opposite set.
A flag does not merely refine a grep search, it redefines what counts as a match, so the very same pattern can return more lines, fewer lines, or precisely the opposite set.
Section 3.1 of 10

3.1 Patterns are regex by default

The PATTERN is a regular expression, not a literal string. This is where characters like . * [ ] have special meaning. For a literal dot, escape with \. or use grep -F (fixed strings).

$ grep '@nus.edu.sg' emails.txt # dots are regex "any character"
$ grep -F '@nus.edu.sg' emails.txt # literal match
Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ echo -e 'hypertension
diabetes
Hypertension' > dx.txt
$ grep h dx.txt
$ grep -i h dx.txt
$ grep -v h dx.txt
Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ grep ,M, cohort_2026.csv | head -n 3
$ grep -c ,F, cohort_2026.csv
$ grep -c ,M, cohort_2026.csv
Section 4 of 10

4 cut - Pick Columns

cut pulls out part of each line. The most common shape is "columns from a delimited file": say what the separator is with -d and which fields (columns) with -f.

$ cat cohort_2026.csv
patient_id,age,sex,height_cm,weight_kg,systolic,diastolic
P-001,54,F,168,72,138,84
P-002,61,M,172,88,152,95
$ cut -d, -f1 cohort_2026.csv
patient_id
P-001
P-002
$ cut -d, -f1,6 cohort_2026.csv
patient_id,systolic
P-001,138
P-002,152
cut treats each line as delimiter-separated fields, where -d declares the separator and -f selects which numbered fields to keep, rejoined with that same delimiter.
cut treats each line as delimiter-separated fields, where -d declares the separator and -f selects which numbered fields to keep, rejoined with that same delimiter.

Field numbers start at 1, not 0. Pick a range with -f2-4 or open-ended -f2- (column 2 to the end). For TSV files use -d$'\t' (the dollar-sign quoting tells bash to interpret \t as a real tab).

Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ cut -d, -f3 cohort_2026.csv
$ cut -d, -f6,7 cohort_2026.csv
cut splits each line on the delimiter and keeps only the fields you name by number, dropping every other column.
cut splits each line on the delimiter and keeps only the fields you name by number, dropping every other column.
Section 5 of 10

5 sort - Put Lines In Order

The sort command is essential for rearranging lines in text files.

$ cat dx.txt
hypertension
diabetes
asthma
$ sort dx.txt
asthma
diabetes
hypertension

By default, it sorts alphabetically, but it becomes incredibly powerful when combined with various flags.

  • sort -n - numeric sort (3 comes before 11; default would put 11 first).
  • sort -r - reverse order.
  • sort -k2 - sort by the SECOND whitespace-separated column.
  • sort -t, -k6 - sort by column 6 in a comma-separated file.
  • sort -u - dedupe as you sort (same as sort | uniq).
Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ sort -t, -k6 -n cohort_2026.csv
By default sort orders lines as text, comparing character by character so 100 falls before 2, while the -n flag compares numeric value to give true number order.
By default sort orders lines as text, comparing character by character so 100 falls before 2, while the -n flag compares numeric value to give true number order.
Section 6 of 10

6 uniq - Squash Adjacent Duplicates

uniq removes duplicate lines that are right next to each other. It does not find duplicates anywhere in the file - they have to be adjacent. That is why you almost always pipe sort | uniq.

$ cat sex_column.txt
F
F
M
F
$ sort sex_column.txt | uniq
F
M
$ sort sex_column.txt | uniq -c
  3 F
  1 M
uniq only collapses duplicate lines that are already adjacent, so piping through sort first groups identical lines together before uniq removes them, and uniq -c reports how many times each line repeated in a row.
uniq only collapses duplicate lines that are already adjacent, so piping through sort first groups identical lines together before uniq removes them, and uniq -c reports how many times each line repeated in a row.

uniq -c (count) is by far the most useful form. Combined with sort -rn it gives you "top items by frequency" in one pipeline: sort | uniq -c | sort -rn.

Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
# Top ages in the cohort, most frequent first
tail -n +2 cohort_2026.csv |
  cut -d, -f2 |
  sort | uniq -c | sort -rn |
  head
Section 7 of 10

7 tr - Translate or Delete Characters

tr works one character at a time. Two main forms: replace each character in set A with the matching character in set B, or delete every character in set A.

$ echo 'Hello World' | tr 'a-z' 'A-Z'
HELLO WORLD
$ echo 'P-001 P-002 P-003' | tr ' ' ','
P-001,P-002,P-003
$ echo 'BMI=28.4' | tr -d 'A-Z='
28.4

tr only reads from stdin - it does NOT take a filename. Pipe a file in with cat or <:

$ tr 'a-z' 'A-Z' < notes.txt > NOTES_LOUD.txt
Try it out

Try this snippet in the Bash Scratchpad on the right.

Try this snippet
$ cat notes.txt | tr 'a-z' 'A-Z'
$ head -n 2 cohort_2026.csv | tr ',' ' '
Section 8 of 10

8 Check your understanding

You have reached the end of the module. Try the same questions again — your answers here, paired with your pre-test answers, are how we measure what the module taught you. Answer every question and confidence rating, then click Submit and see results to view your score.

Post-test

Which command counts how many lines in diagnoses.csv contain the code I10?

Post-test

Which cut command extracts the SECOND column of a comma-separated file?

Post-test

Which pipeline counts how often each value in column 1 of votes.txt appears?

Post-test

Why does uniq usually need sort in front of it?

Post-test

Which command converts all lowercase letters in a file to uppercase?

Post-test

Which grep flag makes the search ignore upper/lower case?

Post-test

What does grep -v error log.txt print?

Post-test

Which command sorts numbers in true numeric order (so 10 comes after 9)?

Post-confidence

I can use grep to find lines matching a pattern and count how many there are.

Not at all confident
Fully confident
Post-confidence

I can extract a single column from a CSV with cut.

Not at all confident
Fully confident
Post-confidence

I can combine sort | uniq -c to count how often each unique value appears.

Not at all confident
Fully confident
Section 9 of 10

9 Your results

Here is how your post-test answers compare with your pre-test answers. The pre/post pairing is the most reliable way to see what this module actually taught you.

Your score

Submit the post-test to see your results.

Muddiest point

What is the one thing from this module that is still unclear to you?

Rate this module

Overall, how would you rate this module?

How likely are you to recommend this module to a peer? (0 = not at all, 10 = extremely likely)