Re: weird bash pipe behavior

2010-01-21 Thread Greg Wooledge
On Wed, Jan 20, 2010 at 07:34:35AM -0800, CptDpondo wrote:
> mencoder  2>&1 | tr '\r' '\n' | grep -v -B 1 '^Pos'
> 
> this eventually creates the correct output, but it's buffered until
> mencoder completes.  I have no idea why; the tr command streams
> without buffering and I've used grep for years and never run into this
> behavior.

grep definitely has this buffering behavior.  If you're using GNU grep,
you can give it the --line-buffered option to change this, at least
according to whichever contributor added that one to
http://mywiki.wooledge.org/BashFAQ/009




Re: weird bash pipe behavior

2010-01-21 Thread Yan Seiner

Greg Wooledge wrote:

On Wed, Jan 20, 2010 at 07:34:35AM -0800, CptDpondo wrote:
  

mencoder  2>&1 | tr '\r' '\n' | grep -v -B 1 '^Pos'

this eventually creates the correct output, but it's buffered until
mencoder completes.  I have no idea why; the tr command streams
without buffering and I've used grep for years and never run into this
behavior.



grep definitely has this buffering behavior.  If you're using GNU grep,
you can give it the --line-buffered option to change this, at least
according to whichever contributor added that one to
http://mywiki.wooledge.org/BashFAQ/009

  
That is the correct solution.  Apparently the behavior is not limited to 
grep; any process in a pipe that's longer than 2 can exhibit this.  
Something about libc behavior...


I replaced grep with awk, ran in to the same problem, and ended up using 
fflush() after scanning each line.


Interesting.  I learned something today.


--

  o__
  ,>/'_ o__
  (_)\(_)   ,>/'_  o__
A day may come  (_)\(_) ,>/'_  o__
when the courage of men fails, (_)\(_) ,>/'_ 
when we forsake our friends and break all (_)\(_)

bonds of fellowship, but it is not this day.
It is not this day!
This day we ride!





Re: weird bash pipe behavior

2010-01-21 Thread Greg Wooledge
On Thu, Jan 21, 2010 at 06:11:10AM -0800, Yan Seiner wrote:
> Greg Wooledge wrote:
> >grep definitely has this buffering behavior.  If you're using GNU grep,
> >you can give it the --line-buffered option to change this, at least
> >according to whichever contributor added that one to
> >http://mywiki.wooledge.org/BashFAQ/009
> >
> That is the correct solution.  Apparently the behavior is not limited to 
> grep; any process in a pipe that's longer than 2 can exhibit this.  
> Something about libc behavior...

It's not the pipeline; it's the command that's doing the writing which
causes the undesired behavior.

Most standard Unix commands will use large buffers when writing if
their stdout is not a terminal.  Compare:

$ for i in {1..10}; do sleep 1; echo $i; done | grep .

$ for i in {1..10}; do sleep 1; echo $i; done | grep . | cat

$ for i in {1..10}; do sleep 1; echo $i; done | while read x; do echo "$x"; 
done | cat

The first one writes a number every second.  The second one writes 10
numbers after 10 seconds.  The grep command buffered its output because
stdout wasn't a terminal in the second case -- hence the --line-buffered
workaround for GNU grep mentioned previously.

The third one writes a number every second despite being a 3-command
pipeline.  The while/read/echo loop doesn't buffer its output the way
grep does.