Mike Taylor dismisses Perl with a pithy reference to a section of its excellent documentation1. For some reason, I mis-remembered that he was complaining about the flip-flop operator rather than context in general.
So, I’ve come to defend the flip-flop operator, and the opposition hasn’t turned up! Oh well, never mind.
Scanning Logfiles
So, say your logfile looks something like this:
... 100,000 lines ... 10:22:25.279 The first interesting line ... 30 more interesting lines ... 10:22:25.772 Another interesting line 10:22:25.772 The last interesting line 10:22:25.779 And then this line isn't interesting any more ... 100,000 lines ...
If you specify the beginning timestamp and end timestamp then you will get one uninteresting line which you can strip with head -n-1.
And that is it. Pretty easy eh?
jared@localhost $ cat flip-flop.muse \ > | perl -ne 'print if /^10:22:25.279/ .. /^10:22:25.779/' \ > | head -n-1 \ > | mail jared 10:22:25.279 The first interesting line ... 30 more interesting lines ... 10:22:25.772 Another interesting line 10:22:25.772 The last interesting line
Notes:
In a regex I often use an unescaped period (.) to match a period if it doesn’t matter like here
And for anyone thinking useless use of cat… it’s deliberate.
1. With impressive inconsistency, he later on says that Perl is a contender to be His Favourite Language which is why the alternative title for this post was Why Mike Taylor is not my Favourite Blogger.
Just kidding Mike.
[...] This post was mentioned on Twitter by Naveed Massjouni, Perl Bits. Perl Bits said: The Perl Flip Flop Operator http://bit.ly/feAuVe [...]
Your deliberate use of cat; would that perhaps be to keep the filename first in a left-to-right reading? If so, you know you can do
$ <flip-flop.muse \
perl -ne ….
Shell redirections can come before the command.
Hi LeoNerd,
That’s a neat trick that I wasn’t aware of, thanks!
But that wasn’t the reason, no. I always process files starting with cat because I usually need to process multiple files and build up my pipelines iteratively. E.g.
cat log2010* | grep blah | awk ‘{ … }’ …
cat log2010* | awk ‘/blah/ { … }’ | perl -ne …
cat log2010* | perl -ne ‘…’
See this question on StackOverflow for some added esoterism:
http://stackoverflow.com/questions/2143554/is-perls-flip-flop-operator-bugged-it-has-global-state-how-can-i-reset-it
You can get rid of the head -n-1 stuff by checking the return value of the flip-flop. The return value is a number representing the count, and when the ending condition is met (i.e. the flip-flop is transitioning from true to false) then this number is returned with a trailing E0 such that it’s still numeric but can be distinguished, that is “5E0″ is still parsed as the number 5 but it’s different than “5″, so:
$ seq 1 100 | perl -ne ‘print if (/^22/ .. /^26/) =~ /^\d+$/’
22
23
24
25
The last line is omitted.
@Evan – I don’t find the behaviour surprising – rather than having global state, I’d say it’s acting like a closure, or an object. If it didn’t behave like this when called multiple times I’d be more surprised.
@Rhombold – that is a neat trick. That’s two things I’ve learned today. Cheers!
It’s the unneccessary use of the flip-flop operator that concerns me.
jared@localhost $ cat flip-flop.muse \
> | perl -ne ‘print if /^10:22:25/ \
> | mail jared
Good point in this specific case Tom. I’ve amended the post to make the utility more obvious.
Thanks.