Pulling one column out of a text file is the most common thing people use AWK for. It takes one short command, but a few small details decide whether you get the right column, a broken one, or a crash on a blank line. This guide covers the command, the options around it, and the mistakes worth knowing about, with sample input and the exact output of each example.
The quick answer
awk '{print $2}' file.txt # second column, split on spaces and tabs
awk -F, '{print $2}' file.csv # second column of a comma-separated file
awk '{print $NF}' file.txt # last column
$1 is the first column, $2 the second, and $NF the last one. If you are new to AWK, read the AWK beginner's guide first for how lines and fields work.
Sample files
Create these once and every example below will work as shown. sales.csv is the same file used in the rest of this series.
echo 'a b c d' > w.txt
cat > sales.csv <<'EOF'
date,region,product,qty,price
2026-10-01,north,pen,10,1.50
2026-10-01,south,book,3,12.00
2026-10-02,north,book,2,12.00
2026-10-02,east,pen,25,1.50
2026-10-03,south,pen,5,1.50
EOF
cat > df.txt <<'EOF'
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 50G 20G 28G 42% /
tmpfs 2.0G 0 2.0G 0% /dev/shm
/dev/sdb1 200G 120G 70G 63% /data
EOF
Print one or more columns
awk '{print $2}' w.txt # b
awk '{print $1, $3}' w.txt # a c
awk '{print $1 $3}' w.txt # ac
awk '{print $1 "-" $3}' w.txt # a-c
A comma inside print inserts the output separator, which is a space by default. Without the comma the values are glued together. If you want to join them with something else, either put your own text between them (the last line) or change the output separator once in a BEGIN block:
awk 'BEGIN {OFS=","} {print $1, $3}' w.txt # a,c
Choose the delimiter
AWK splits on runs of spaces and tabs unless you tell it otherwise. Use -F for anything else:
awk -F, '{print $2}' sales.csv # CSV: region, north, south ...
awk -F: '{print $1, $NF}' <<< 'root:x:0:0:root:/root:/bin/bash'
# root /bin/bash
awk -F'\t' '{print $2}' file.tsv # tab-separated
The <<< in the second example is a bash and zsh here-string that feeds a short text to the command; in plain sh, use echo '...' | awk ... instead. The details of separators, including several at once, are in the field separator guide.
The last column and the one before it
NF is the number of fields on the current line, so $NF is the last field and $(NF-1) is the one before it. This works even when lines have different numbers of columns:
awk '{print $NF}' w.txt # d
awk '{print $(NF-1)}' w.txt # c
The parentheses matter. Without them, AWK reads $NF-1 as "the last field, minus one":
echo '5 10' | awk '{print $NF-1}' # 9, not the 5
Print everything except the first column
There is no "all but the first" shortcut, but there are three ways to do it. Setting $1 to an empty string leaves a stray leading space, because AWK rebuilds the line with its output separator:
awk '{ $1=""; print }' w.txt # " b c d" (note the leading space)
awk '{ $1=""; print substr($0,2) }' w.txt # b c d
The loop version has no such problem, and it also lets you print any range of columns:
awk '{ for (i=2; i<=NF; i++) printf "%s%s", $i, (i<NF ? OFS : ORS) }' w.txt
# b c d
printf 'a b c d e f\n' | awk -v from=2 -v to=4 \
'{ for (i=from; i<=to; i++) printf "%s%s", $i, (i<to ? OFS : ORS) }'
# b c d
Skip the header and filter rows
Put a condition in front of the braces. NR>1 skips the first line; a field test keeps only some rows:
awk 'NR>1 {print $1, $5}' df.txt
# /dev/sda1 42%
# tmpfs 0%
# /dev/sdb1 63%
awk -F, '$2=="north" {print $3}' sales.csv
# pen
# book
Pick a column by its header name
Counting columns gets fragile when someone adds one to the file. If the first line is a header, you can look columns up by name instead. Read the header into an array on line 1, then use the array as the column number:
awk -F, 'NR==1 {for (i=1; i<=NF; i++) col[$i]=i; next}
{print $col["product"], $col["price"]}' sales.csv
pen 1.50
book 12.00
book 12.00
pen 1.50
pen 1.50
next tells AWK to stop processing the header line and move on to the next one. If the file gains a new column, this command keeps working.
Take the column number from a shell variable
awk -v col=3 '{print $col}' w.txt # c
Because the number comes from outside, one script can print a different column each time, for example awk -v col="$1" '{print $col}' file.txt inside a shell script.
Unique values from a column
awk -F, 'NR>1 {print $2}' sales.csv | sort -u
# east
# north
# south
awk -F, 'NR>1 && !seen[$2]++ {print $2}' sales.csv # keeps first-seen order
# north
# south
# east
Problems and fixes
The column has spaces inside it
With the default splitting, a tab-separated file where a name contains a space gives you half the name:
printf 'id\tname\tcity\n1\tAda Lovelace\tLondon\n' | awk 'NR>1 {print $2}'
# Ada
printf 'id\tname\tcity\n1\tAda Lovelace\tLondon\n' | awk -F'\t' 'NR>1 {print $2}'
# Ada Lovelace
Set the separator to a tab with -F'\t'.
Parsing ls -l output
A file name with a space is split into several fields, so $9 returns only the first word and $NF returns only the last one. In my test, a file called my report.txt gave my for $9 and report.txt for $NF. Do not parse ls output when names may contain spaces; use find or a shell glob instead.
A blank line crashes $(NF-1)
On an empty line NF is 0, so $(NF-1) asks for field -1. Both gawk and mawk stop with an error and exit code 2 (gawk says "attempt to access field -1", mawk says "negative field index $-1"). On a line with only one field, $(NF-1) is $0, the whole line. Guard it with a condition:
awk 'NF>1 {print $(NF-1)}' file.txt
Files from Windows (CRLF line endings)
Each line ends in a hidden carriage return, which becomes part of the last field. od -c shows it:
awk -F, '{print $NF "|"}' crlf.csv | od -c
# b \r | \n
Remove it first:
awk -F, '{sub(/\r$/,""); print $NF "|"}' crlf.csv
# b|
# d|
CSV fields with commas inside quotes
Splitting on -F, cannot know that "hi, there" is one value. On the line Ada,"hi, there", field 2 is "hi and field 3 is there". For real CSV files you need a parser; this is covered in the CSV article of this series.
Frequently asked questions
How do I print the last column in AWK?
Use $NF. For the second to last, use $(NF-1).
How do I print columns 2 to 4?
Use the range loop shown above, with from=2 and to=4.
How do I print a column when the delimiter is a comma?
Add -F,, for example awk -F, '{print $3}' file.csv.
What is the difference between print $1, $2 and print $1 $2?
The comma puts the output separator (a space by default) between the values. Without it they are joined with nothing in between.
Originally published on DEV Talk.
Top comments (0)