4

I am trying to debug one scenario by checking the logs, here is my command

tail -f eclipse.log | grep 'enimation' | grep  -i 'tap'

Basically what I am trying to to is that, of all of the line, I am printing lines with enimation in it, then of all of the animation, I want to see the animation with "tap" in it.

Here is the sammple data for which it is returning empty results

*******enimation error*********TapExpand
*******enimation error*********TapShrink

This is returning empty results.

While if I run this command

 tail -f eclipse.log | grep  -i 'enimation.*tap'

it returns correct results. Can someone please explain to me, what is the difference between the above two command and why there is a discrepancy in the results. They both seem identical to me.

Max
  • 9,100
  • 25
  • 72
  • 109
  • Definitely a duplicate of that question. But I think [an answer](http://stackoverflow.com/a/9752465/3076724) from a slightly different question actually does a better job of explaining the problem. – Reinstate Monica Please Oct 14 '14 at 16:16

4 Answers4

7

grep is buffering it's output. To tell GNU grep to spit out output line-by-line you need to use --line-buffered option in grep to make it work:

tail -f eclipse.log | grep --line-buffered 'enimation' | grep --line-buffered -i 'tap'

As per man grep:

--line-buffered
    Force output to be line buffered.  By default, output is line buffered when standard
    output is a terminal and block buffered otherwise.
anubhava
  • 761,203
  • 64
  • 569
  • 643
3

The output of the grep in the middle is not a terminal, so it is using block buffering instead of line buffering. You have to force line buffering using --line-buffered option.

tail -f eclipse.log | grep --line-buffered 'enimation' | grep  -i 'tap'

In case of other commands, which don't provide such an option, you can use stdbuf command to force line buffering, e.g.:

tail -f eclipse.log | stdbuf -o1 grep 'enimation' | grep  -i 'tap'
danadam
  • 3,350
  • 20
  • 18
1

Your output is getting buffered. Try:

tail -f eclipse.log | grep --line-buffered 'enimation' | grep --line-buffered -i 'tap'
Raul Andres
  • 3,766
  • 15
  • 24
-2

Try adding the -E option to grep. A lot of reflex features don't work without it. I usually refer to it as the "yes, I do know what I'm doing" option.

whereswalden
  • 4,819
  • 3
  • 27
  • 41
  • -1 Complete red herring. There are no extended regular expression features in the question. – tripleee Oct 14 '14 at 14:46
  • `-E` option is the short form of `--extended-regexp`. From man: `Interpret PATTERN as an extended regular expression`. In this case, PATTERN is 'enimation' and it doesn't change whether is interpreted as a *extended-regexp* – whoan Oct 14 '14 at 16:50
  • The -E option might help if we want to filter by both patterns enimation **and** tap but not if we want to filter _first_ enimation _then_ tap if tap is anywhere in the line... a proper way to achieve the first case is `tail -f eclipse.log | grep -iE "enimation|tap"` or `tail -f eclipse.log | grep -iE "enimation.*tap"` if we are sure about the sequence (tap always being after enimation), all this to prevent performance issues about --line-buffered option. – MediaVince Aug 18 '16 at 09:52