Printing the last column of a line in a file
Asked Answered
P

11

195

I have a file that is constantly being written to/updated. I want to find the last line containing a particular word, then print the last column of that line.

The file looks something like this. More A1/B1/C1 lines will be appended to it over time.

A1 123 456
B1 234 567
C1 345 678
A1 098 766
B1 987 6545
C1 876 5434

I tried to use

tail -f file | grep A1 | awk '{print $NF}'

to print the value 766, but nothing is output.

Is there a way to do this?

Pervious answered 24/10, 2012 at 9:13 Comment(0)
H
285

You don't see anything, because of buffering. The output is shown, when there are enough lines or end of file is reached. tail -f means wait for more input, but there are no more lines in file and so the pipe to grep is never closed.

If you omit -f from tail the output is shown immediately:

tail file | grep A1 | awk '{print $NF}'

@EdMorton is right of course. Awk can search for A1 as well, which shortens the command line to

tail file | awk '/A1/ {print $NF}'

or without tail, showing the last column of all lines containing A1

awk '/A1/ {print $NF}' file

Thanks to @MitchellTracy's comment, tail might miss the record containing A1 and thus you get no output at all. This may be solved by switching tail and awk, searching first through the file and only then show the last line:

awk '/A1/ {print $NF}' file | tail -n1
Harmonica answered 24/10, 2012 at 9:17 Comment(2)
You never need grep+awk since awk can do it's own RE comparison. "grep A1 | awk '{print $NF}'" should just be "awk '/A1/{print $NF}'". Also, if you aren't using tail -f then you don't need tail at all, yoiu can just do: awk '/A1/{f=$NF} END{print f}' fileGranitite
This isn't quite right, as the column may not appear in the window that raw tail gives you. Unless you know it is going to appear with a certain frequency, it would be safer to awk '/A1/ {print $NF}' file | tail -n1.Westernize
M
41

To print the last column of a line just use $(NF):

awk '{print $(NF)}' 
Matriculation answered 5/4, 2017 at 20:20 Comment(1)
Why not just $NF?Catcher
S
14

One way using awk:

tail -f file.txt | awk '/A1/ { print $NF }'
Suavity answered 24/10, 2012 at 10:13 Comment(3)
I thought that was the right solution to the posted problem (+1!) but now I see I don't understand the question. The OP wants the last field from the LAST LINE of the file, but there is no LAST LINE if you're using tail -f. Maybe he means the last line CURRENTLY in the file, in which case see one of my other comments.Granitite
Very good and simple. Thumbs up. Thumbs down for awk's cryptic syntax :)Ops
awk's syntax might appear cryptic nowadays, but it was really ahead of its time. In 1977 (when awk was born), C was a kindergartener (at 5yo), and C++ a glimmer in Bjarne's eye. It's the only language I use where it's normal to include your entire program as a command-line parameter! I might be biased, though, since I've always been a bit awk-ward. ;)Kinnikinnick
S
12

You can do this without awk with just some pipes.

tac file | grep -m1 A1 | rev | cut -d' ' -f1 | rev
Solutrean answered 24/10, 2012 at 9:22 Comment(1)
This solves your problem, but it doesn't really use awk. Hope it's good enough for you anyway.Solutrean
F
4

maybe this works?

grep A1 file | tail -1 | awk '{print $NF}'
Furfur answered 24/10, 2012 at 9:19 Comment(0)
G
4

Not the actual issue here, but might help some one: I was doing awk "{print $NF}", note the wrong quotes. Should be awk '{print $NF}', so that the shell doesn't expand $NF.

Galleass answered 27/11, 2019 at 9:28 Comment(0)
S
2

You can do all of it in awk:

<file awk '$1 ~ /A1/ {m=$NF} END {print m}'
Sesame answered 24/10, 2012 at 10:29 Comment(1)
You don't need split() and an array, just save the last field and print that: awk '/A1/{f=$NF} END{print f}' fileGranitite
S
2

Using Perl

$ cat rayne.txt
A1 123 456
B1 234 567
C1 345 678
A1 098 766
B1 987 6545
C1 876 5434


$ perl -lane ' /A1/ and $x=$F[2] ; END { print "$x" } ' rayne.txt
766

$
Scriven answered 9/2, 2019 at 14:8 Comment(2)
Looks too complicated, just do perl -lane 'print $F[2] if /A1/' rayne.txtSerles
@Hi-Angel..the question asks for last occurrence of A1. your answer will print all matches.. btw if you like my answer, pls upvote itScriven
C
1

awk -F " " '($1=="A1") {print $NF}' FILE | tail -n 1

Use awk with field separator -F set to a space " ".

Use the pattern $1=="A1" and action {print $NF}, this will print the last field in every record where the first field is "A1". Pipe the result into tail and use the -n 1 option to only show the last line.

Cockcrow answered 4/12, 2018 at 14:14 Comment(0)
S
0

Execute this on the file:

awk 'ORS=NR%3?" ":"\n"' filename

and you'll get what you're looking for.

Samoyed answered 31/1, 2013 at 17:14 Comment(0)
G
-3

ls -l | awk '{print $9}' | tail -n1

Gamelan answered 23/2, 2017 at 19:38 Comment(1)
How is this even related to the OP's question?Whaleback

© 2022 - 2024 — McMap. All rights reserved.