This is simple, short, and easy to write, understand, and check, and I personally like it:
grep -oE '\S+$' file
grep
in Ubuntu, when invoked with -E
or -P
, takes the shorthand \s
to mean a whitespace character (in practice usually a space or tab) and \S
to mean anything that isn't one. Using the quantifier +
and the end-of-line anchor $
, the pattern \S+$
matches one or more non-blanks at the end of a line. You can use -P
instead of -E
; the meaning in this case is the same but a different regular expressions engine is used, so they may have different performance characteristics.
This is equivalent to Avinash Raj's commented solution (just with an easier, more compact syntax):
grep -o '[^[:space:]]\+$' file
These approaches won't work if there could be trailing whitespace after the number. They can be modified so they do, but I see no point in going into that here. Although it's sometimes instructive to generalize a solution to work under more cases, it's not practical to do so nearly as often as people tend to assume, because one usually has no way to know in which of many different incompatible ways the problem might ultimately need to be generalized.
Performance is sometimes an important consideration. This question doesn't stipulate that the input is very large, and it's likely that every method that has been posted here is fast enough. However, in case speed is desired, here's a small benchmark on a ten million line input file:
$ perl -e 'print((<>) x 2000000)' file > bigfile
$ du -sh bigfile
439M bigfile
$ wc -l bigfile
10000000 bigfile
$ TIMEFORMAT=%R
$ time grep -o '[^[:space:]]\+$' bigfile > bigfile.out
819.565
$ time grep -oE '\S+$' bigfile > bigfile.out
816.910
$ time grep -oP '\S+$' bigfile > bigfile.out
67.465
$ time cut -d= -f2 bigfile > bigfile.out
3.902
$ time grep -o '[^[:space:]]\+$' bigfile > bigfile.out
815.183
$ time grep -oE '\S+$' bigfile > bigfile.out
824.546
$ time grep -oP '\S+$' bigfile > bigfile.out
68.692
$ time cut -d= -f2 bigfile > bigfile.out
4.135
I ran it twice in case the order mattered (as it sometimes does for I/O-heavy tasks) and because I didn't have a machine available that wasn't doing other stuff in the background that could skew the results. From those results I conclude the following, at least provisionally and for input files of the size I used:
Wow! Passing -P
(to use PCRE) rather than -G
(the default when no dialect is specified) or -E
made grep
faster by over an order of magnitude. So for large files, it may be better to use this command than the one shown above:
grep -oP '\S+$' file
WOW!! The cut
method in αғsнιη's answer, cut -d= -f2 file
, is over an order of magnitude quicker than even the faster version of my way! It was the winner in pa4080's benchmark as well, which covered more methods than this but with smaller input--and which is why I chose it, of all the other methods, to include in my test. If performance is important or files are huge, I think αғsнιη's cut
method should be used.
This also serves as a reminder that the simple cut
and paste
utilities shouldn't be forgotten, and should perhaps be preferred when applicable, even though there are more sophisticated tools like grep
that are often offered as first-line solutions (and that I am personally more accustomed to using).
grep -o '[^[:space:]]\+$' file
\S+$
with either-E
or-P
.) So this kind of solution isn't inherently slow. But I still can't get it anywhere close to αғsнιη'scut
method, which won your benchmark too.