Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm reading from a serial port connected to a gps device sending nmea strings.

A simplified invocation to illustrate my point:

  $ awk '{ print $0 }' /dev/ttyPSC9 
  GPGGA,073651.000,6310.1043,N,01436.1539,E,1,07,1.0,340.2,M,33.3,M,,0000*56
  $GPGSA,A,3,28,22,09,27,01,19,17,,,,,,2.3,1.0,2.0*39
  $GPRMC,073651.000,A,6310.1043,N,01436.1539,E,0.42,163.42,070312,,,A*67
  GPGGA,073652.000,6310.1043,N,01436.1540,E,1,07,1.0,339.2,M,33.3,M,,0000*55
  $GPGSA,A,3,28,22,09,27,01,19,17,,,,,,2.3,1.0,2.0*39

If I instead try to read from a pipe, awk buffers the input before sending it to stdout.

$ cat /dev/ttyPSC9 | awk '{ print $0 }'
<long pause>
GPGGA,073651.000,6310.1043,N,01436.1539,E,1,07,1.0,340.2,M,33.3,M,,0000*56
$GPGSA,A,3,28,22,09,27,01,19,17,,,,,,2.3,1.0,2.0*39
$GPRMC,073651.000,A,6310.1043,N,01436.1539,E,0.42,163.42,070312,,,A*67
GPGGA,073652.000,6310.1043,N,01436.1540,E,1,07,1.0,339.2,M,33.3,M,,0000*55
$GPGSA,A,3,28,22,09,27,01,19,17,,,,,,2.3,1.0,2.0*39

How can I avoid the buffering?

Edit: Kyle Jones suggested that cat is buffering it's output but that doesn't appear to be happening:

$ strace cat /dev/ttyPSC9 | awk '{ print $0 }'
write(1, "2,"..., 2)                    = 2
read(3, "E"..., 4096)                   = 1
write(1, "E"..., 1)                     = 1
read(3, ",0"..., 4096)                  = 2

When I think about it: I thought that a program used line buffering when writing to a terminal and "regular buffering" for all other cases. Then, why is cat not buffering more? Is the serial port signaling EOF? Then why is cat not terminated?

share|improve this question
1  
BashFAQ 009 may be useful. –  jw013 Mar 7 '12 at 8:21
    
@jw013: Thanks for the link, a great sum up of how buffering works in bash. –  dannas Mar 7 '12 at 8:31
add comment

3 Answers

up vote 4 down vote accepted

It is likely to be buffering in awk, not cat. In the first case, awk believes it is interactive because it's input and output are ttys (even though they're different ttys - I'm guessing that awk is not checking that). In the second, the input is a pipe so it runs non-interactively.

You will need to explicitly flush in your awk program. This is not portable though.

For more background and details on how to flush output, read: http://www.gnu.org/software/gawk/manual/html_node/I_002fO-Functions.html

share|improve this answer
2  
Thanks for the explanation. awk -W interactive '{print $0}' appears to do the trick. The 'W interactive option is available on my awk version (mawk 1.2) but I dunno if it's a standard option. –  dannas Mar 7 '12 at 8:29
1  
@dannas -W is not in the POSIX standard for awk. I'm not sure what to do if you need maximum portability. –  jw013 Mar 7 '12 at 8:46
    
I'm accepting this answer since it explains why awk is doing full buffering in my example, instead of line buffering - it checks the if the input is a tty as well as the output. I only thought that it would check the output. –  dannas Mar 7 '12 at 8:57
    
@jw013: Thanks for looking up the standard. For me, I just wanted to understand why awk was doing full buffering and I think I do now. –  dannas Mar 7 '12 at 9:00
add comment

I know it is an old question, but a one-liner may help those who come here searching:

cat /dev/ttyPSC9 | awk '{ print $0; system("")}'

system("") does the trick, and is POSIX compliant. Non-posix systems: beware.

share|improve this answer
    
This worked for me –  redolent Jan 1 at 3:20
add comment

It's probably cat buffering its output. Use cat -u to disable the buffering.

share|improve this answer
    
No. strace cat /dev/ttyPSC9 | awk '{ print $0 }' write(1, "2,"..., 2) = 2 read(3, "E"..., 4096) = 1 write(1, "E"..., 1) = 1 read(3, ",0"..., 4096) = 2 –  dannas Mar 7 '12 at 8:05
    
cat -u is ignored on my system (debian lenny). –  dannas Mar 7 '12 at 8:06
1  
Just wanted to add a link to the LD_PRELOAD hack for controlling buffer behaviour of existing programs without a recompilation. I also found out that since coreutils 7.5, stdbuf is available and essentially does the same thing. –  dannas Mar 7 '12 at 9:21
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.