파이프에서 읽을 때 awk가 전체 버퍼링을 수행하는 이유


23

nmea 문자열을 보내는 gps 장치에 연결된 직렬 포트에서 읽습니다.

내 요점을 설명하기위한 간단한 호출 :

  $ 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

대신 파이프에서 읽으려고하면 awk가 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

버퍼링을 피하려면 어떻게해야합니까?

편집 : Kyle Jones는 cat이 출력을 버퍼링한다고 제안했지만 발생하지 않는 것으로 보입니다.

$ 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

내가 생각할 때 : 프로그램은 터미널에 쓸 때 라인 버퍼링을 사용하고 다른 모든 경우에는 "일반 버퍼링"을 사용한다고 생각했습니다. 그러면 왜 고양이가 더 버퍼링하지 않습니까? 직렬 포트 신호가 EOF입니까? 그러면 왜 고양이가 끝나지 않습니까?


1
BashFAQ 009 가 유용 할 수 있습니다.
jw013

@ jw013 : bash에서 버퍼링이 작동하는 방식에 대한 요약입니다.
Daniel Näslund

답변:


10

고양이가 아닌 awk에서 버퍼링 될 가능성이 있습니다. 첫 번째 경우 awk는 입력 및 출력이 TTY이므로 대화 형이라고 생각합니다 (TTY가 다르더라도 awk가 확인하지 않는 것 같습니다). 두 번째로 입력은 파이프이므로 비 대화식으로 실행됩니다.

awk 프로그램을 명시 적으로 플러시해야합니다. 그러나 이것은 이식성이 없습니다.

출력을 비우는 방법에 대한 자세한 내용과 내용은 http://www.gnu.org/software/gawk/manual/html_node/I_002fO-Functions.html을 참조하십시오.


6
설명 주셔서 감사합니다. awk -W interactive '{print $0}'트릭을 수행하는 것으로 보입니다. 'W interactive옵션은 내 AWK 버전 (mawk의 1.2)로 볼 수 있지만, 표준 옵션이 있다면 난 몰라.
Daniel Näslund

1
@dannas -W는의 POSIX 표준에 없습니다awk . 최대한의 이식성이 필요한 경우 어떻게해야할지 모르겠습니다.
jw013

awk가 라인 버퍼링 대신 내 예제에서 전체 버퍼링을 수행하는 이유를 설명하기 때문에이 답변을 수락합니다. 입력이 tty 및 출력인지 확인합니다. 나는 그것이 출력을 확인할 것이라고 생각했습니다.
Daniel Näslund

@ jw013 : 표준을 찾아 주셔서 감사합니다. 나를 위해 awk가 전체 버퍼링을하는 이유를 이해하고 싶었고 지금은 생각합니다.
Daniel Näslund

@dannas 나는 -W interactive적어도 awk의 우분투 12.04 (그리고 아마도 더 새로운) 배포판에서 지원되는 것을 확인할 수 있습니다 .
Jason C

37

나는 그것이 오래된 질문이라는 것을 알고 있지만 한 명의 라이너가 여기에 오는 사람들을 도울 수 있습니다.

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

system("")트릭을 수행하고 POSIX를 준수합니다. 비 POS 시스템 :주의하십시오.

fflush()동일한 기능 을 수행하지만 이전 버전의 awk에서는 사용할 수없는 보다 구체적인 기능 이 있습니다.

사용에 관한 문서 의 중요한 정보 system(""):

gawk는 system () 함수의 이러한 사용을 특별한 경우로 취급하며 빈 명령으로 쉘 (또는 다른 명령 인터프리터)을 실행하지 않을 정도로 똑똑합니다. 따라서 gawk를 사용하면이 관용구는 유용 할뿐만 아니라 효율적입니다.


이것은 나를 위해 일했다
redolent

3
내 또는도 awk아무것도하지 fflush()않습니다 system(""). 내는 gawk비록 영광.
Krzysztof Jabłoński
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.