All I want is the last two columns printed.
-
6Not quite sure why this has 87 upvotes, it can certainly be improved with an example at the very least. – Arj May 11 '17 at 12:00
-
1Probably because the question is extremely simple by nature and easily understood without an example, which is rare, but in this case it appears to work. The problem here is not lack of information I think, but more that it shows a lack of independent research. – DryLabRebel Aug 06 '20 at 22:57
-
This question is also a duplicate of [this](https://stackoverflow.com/questions/2096490/print-second-last-column-field-in-awk?rq=1) question. – DryLabRebel Aug 06 '20 at 23:14
-
1Does this answer your question? [Print second last column/field in awk](https://stackoverflow.com/questions/2096490/print-second-last-column-field-in-awk) – DryLabRebel Aug 06 '20 at 23:15
6 Answers
You can make use of variable NF
which is set to the total number of fields in the input record:
awk '{print $(NF-1),"\t",$NF}' file
this assumes that you have at least 2 fields.

- 445,704
- 82
- 492
- 529
-
1You need a comma - since we are being picky today: space concatenates fields, comma separates fields in a print statement. That will merge the two fields – jim mcnamara Nov 29 '10 at 15:06
-
20Now you're printing "field-OFS-tab-OFS-field". It should be `awk '{print $(NF-1) "\t" $NF}' file` or `awk '{print $(NF-1), $NF}' file` or `awk 'BEGIN{OFS="\t"} {print $(NF-1), $NF}' file`. – Dennis Williamson Nov 29 '10 at 17:06
-
1Just to add to the previous comment, the problem with using `'{print $x,"\t",$y}'` is that awk interprets each comma separated variable as it's own field, so the result will actually be `field1
– DryLabRebel Aug 06 '20 at 22:51field2`, (because it will use white space delimiter by default) as opposed to `field1 field2` which is probably what you're expecting. using Output Field Separator (OFS) is almost always what you want.
awk '{print $NF-1, $NF}' inputfile
Note: this works only if at least two columns exist. On records with one column you will get a spurious "-1 column1"

- 16,005
- 2
- 34
- 51
-
3Try and see. It does work Solaris 9 awk & nawk. The alternative is $(NF-1) – jim mcnamara Nov 29 '10 at 15:04
-
1@coaddict - I'm guessing you haven't worked with different awk implementations. Old awks behaviors have been (maybe erroneously) brought forward. I do not have gawk to test against -- which is probably what you are referencing. So I don't know for sure why your comment came abnput. Linux awk out of the box usually is gawk. I will test and post back. Meanwhile try Soalris or HPUX or DGX or whatever to see what I mean by old awk. – jim mcnamara Nov 29 '10 at 15:14
-
6You probably got tricked into thinking it worked because you tried `echo 1 2 3 | awk ...`. `$NF-1` is `($NF) - 1` in every `awk` implementation. – Stephane Chazelas Feb 09 '14 at 15:55
-
The "One True Awk" source code has more than 40 conflicts in the `yacc` grammar, which is ironic given what the A stands for in awk. Different versions of awk parsing things differently? Big surprise! – Kaz Feb 21 '14 at 06:01
-
The fact that you state that with one-column input you get `-1` as the first output token indicates that @StephaneChazelas is right. If your claim about "old" awk's behavior were correct, the first token should effectively be `$0` i.e., the entire input line. Since the entire input line is just one token in this case - the first and only column - you should get that one column value *twice*. – mklement0 Feb 24 '14 at 01:55
-
awk -V | head -n1 ; echo '1 2 3 4 5' | awk '{print $NF-1,$NF}' ....... GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.3, GNU MP 6.1.0) ....... 4 5 .... this is working on this awk version, I tried this piece of code some years ago and didn't worked, so, if this answer is right or wrong depends on awk version – THESorcerer Apr 27 '16 at 08:33
-
1@THESorcerer, try with `echo '5 4 3 2 1' | awk '{print $NF-1,$NF; print $(NF-1), $NF}'` -- or any other input where the 2nd last field is not one less than the last field. – glenn jackman Apr 30 '18 at 20:24
-
`nawk`, `mawk` and `gawk` on Ubuntu and `awk` on macOS all need the parens. Even [Heirloom `oawk`](http://heirloom.sourceforge.net/tools.html) does. – Dennis Williamson Oct 09 '18 at 21:19
@jim mcnamara: try using parentheses for around NF
, i. e. $(NF-1)
and $(NF)
instead of $NF-1
and $NF
(works on Mac OS X 10.6.8 for FreeBSD awk
and gawk
).
echo '
1 2
2 3
one
one two three
' | gawk '{if (NF >= 2) print $(NF-1), $(NF);}'
# output:
# 1 2
# 2 3
# two three
-
We had already considered () earlier. I thought we were discussing where the original old awk behavior came from. – jim mcnamara Oct 19 '13 at 15:44
-
+1 for an answer with explicit `$(NF-1)` - which at the very least is more portable than `$NF-1`; it's definitely less ambiguous. `$(NF)` is overkill, though - just `$NF` will do. Guarding against lines with fewer than 2 columns is worthwhile too, as with one-column lines you'd get the first column value *twice*, and with zero-column - i.e., empty - lines the awk command would fail altogether, due to an attempt to access a field with index -1. – mklement0 Feb 24 '14 at 02:33
-
We can make it, I think, a little shorter: `gawk 'NF>=2 {print $(NF-1), $NF}'` – SergioAraujo Nov 08 '20 at 10:05
using gawk exhibits the problem:
gawk '{ print $NF-1, $NF}' filename
1 2
2 3
-1 one
-1 three
# cat filename
1 2
2 3
one
one two three
I just put gawk on Solaris 10 M4000: So, gawk is the cuplrit on the $NF-1 vs. $(NF-1) issue. Next question what does POSIX say? per:
http://www.opengroup.org/onlinepubs/009695399/utilities/awk.html
There is no direction one way or the other. Not good. gawk implies subtraction, other awks imply field number or subtraction. hmm.

- 382,024
- 64
- 607
- 775

- 16,005
- 2
- 34
- 51
-
1The first 2 lines of your sample input file are not helpful in that they produce the same output with _either_ behavior. Can you please reconfirm that Solaris awk does indeed NOT behave like gawk in this case? – mklement0 Feb 24 '14 at 02:46
-
As for your link to the awk spec: The anecdotal argument for using `$(NF-1)` is that the two examples of computing the field index in the spec both use that form: `$(NF-1)` and `$(NF+2)`. Then there's the "Expressions in awk" section, which lists `$expr` as having [much] higher precedence than `expr - expr`. Since `NF` is an expression itself, `$NF-1` should evaluate to `($NF)-1`. Even IF, after all, there are indeed awk implementations out there that evaluate `$NF-1` as `$(NF-1)`, the lesson learned here is that using `$(NF-1)` is the safe and portable choice. – mklement0 Feb 24 '14 at 02:54
Please try this out to take into account all possible scenarios:
awk '{print $(NF-1)"\t"$NF}' file
or
awk 'BEGIN{OFS="\t"}' file
or
awk '{print $(NF-1), $NF} {print $(NF-1), $NF}' file

- 8,923
- 3
- 18
- 24

- 26,333
- 8
- 32
- 52
try with this
$ cat /tmp/topfs.txt
/dev/sda2 xfs 32G 10G 22G 32% /
awk print last column
$ cat /tmp/topfs.txt | awk '{print $NF}'
awk print before last column
$ cat /tmp/topfs.txt | awk '{print $(NF-1)}'
32%
awk - print last two columns
$ cat /tmp/topfs.txt | awk '{print $(NF-1), $NF}'
32% /

- 297
- 1
- 5