views:

1507

answers:

5

I'm writing a small shell script that needs to reverse the lines of a text file. Is there a standard filter command to do this sort of thing?

My specific application is that I'm getting a list of Git commit identifiers, and I want to process them in reverse order:

git log --pretty=oneline work...master | grep -v DEBUG: | cut -d' ' -f1 | reverse

The best I've come up with is to implement reverse like this:

... | cat -b | sort -rn | cut -f2-

This uses cat to number every line, then sort to sort them in descending numeric order (which ends up reversing the whole file), then cut to remove the unneeded line number.

The above works for my application, but may fail in the general case because cat -b only numbers nonblank lines.

Is there a better, more general way to do this?

+7  A: 

Answer is not 42 but tac.

Edit: Slower but more memory consuming using sed

sed 'x;1!H;$!d;x'

and even longer

perl -e'print reverse<>'
Hynek -Pichi- Vychodil
Cryptic, but that's what I was looking for. Thanks!
Greg Hewgill
'tac' isn't cryptic: it's 'cat' in reverse. ;-)
Charlie Martin
That's true, but I sure wouldn't have guessed that without knowing beforehand. You could call the sort program "abc" which makes sense in the same way but wouldn't help somebody guess its name!
Greg Hewgill
+12  A: 

In GNU coreutils, there's tac(1)

Vinko Vrsalovic
Damn whatever is the guilty party, the answer notifier doesn't always work for me :/
Vinko Vrsalovic
A: 
:   "@(#)$Id: reverse.sh,v 1.2 1997/06/02 21:45:00 johnl Exp $"
#
#   Reverse the order of the lines in each file

awk ' { printf("%d:%s\n", NR, $0);}' $* |
sort -t: +0nr -1 |
sed 's/^[0-9][0-9]*://'

Works like a charm for me...

Jonathan Leffler
O(N.log(N)) vs O(N) `tac` and `sed` = Less effective approach you can't think up? I think that there can be O(N!), try found it.
Hynek -Pichi- Vychodil
I use it a couple of times a month, typically on a up to a few hundred lines of code. It's fine for that. If I needed it every day, on gigabyte files, then I'd reconsider. I wrote it in 1989; I altered the ID string notation in 1997. It's stable code. And 'tac' is not standard on Solaris.
Jonathan Leffler
But there is `sed` on Solaris I guess, thus you can use more effective sed 'x;1!H;$!d;x'
Hynek -Pichi- Vychodil
Probably - I don't use it to process such large files that it matters that sort spills the data to disk if needed but the sed version crashes if there's no memory space left for it to grab. If it was a performance problem, I'd consider moving; it isn't (for me) so I'm probably too lazy to change.
Jonathan Leffler
It's true. sed is not cache data to disk as sort does. I don't know if tac is not affected with same bug ;-)
Hynek -Pichi- Vychodil
+1  A: 
cat -b only numbers nonblank lines"


If that's the only issue you want to avoid, then why not use "cat -n" to number all the lines?

Good point, I guess I didn't read far enough through the man page to find -n. In any case, tac is what I really wanted.
Greg Hewgill
A: 

Similar to the sed example above, using perl - maybe more memorable (depending on how your brain is wired):

perl -e 'print reverse <>'
Gavin Brock