Perché awk esegue il buffering completo quando legge da una pipe


23

Sto leggendo da una porta seriale collegata a un dispositivo gps che invia stringhe nmea.

Un'invocazione semplificata per illustrare il mio punto:

  $ 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

Se invece provo a leggere da una pipe, awk inserisce nel buffer l'input prima di inviarlo a 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

Come posso evitare il buffering?

Modifica : Kyle Jones ha suggerito che cat sta eseguendo il buffering del suo output ma ciò non sembra accadere:

$ 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

Quando ci penso: ho pensato che un programma utilizzava il buffering di linea quando scriveva su un terminale e il "buffering regolare" per tutti gli altri casi. Quindi, perché il gatto non sta tamponando di più? La porta seriale segnala EOF? Allora perché il gatto non è terminato?


1
BashFAQ 009 può essere utile.
jw013

@ jw013: grazie per il link, un ottimo riassunto di come funziona il buffering in bash.
Daniel Näslund

Risposte:


10

È probabile che sia buffering in awk, non in cat. Nel primo caso, awk ritiene che sia interattivo perché i suoi input e output sono TTY (anche se sono TTY diversi - immagino che awk non lo stia verificando). Nel secondo, l'input è una pipe, quindi viene eseguito in modo non interattivo.

Dovrai scaricare esplicitamente il tuo programma awk. Questo non è portatile, però.

Per ulteriori informazioni e dettagli su come scaricare l'output, leggi: http://www.gnu.org/software/gawk/manual/html_node/I_002fO-Functions.html


6
Grazie per la spiegazione. awk -W interactive '{print $0}'sembra fare il trucco. L' 'W interactiveopzione è disponibile sulla mia versione di awk (mawk 1.2) ma non so se è un'opzione standard.
Daniel Näslund

1
@dannas -Wnon è nello standard POSIX perawk . Non sono sicuro di cosa fare se hai bisogno della massima portabilità.
jw013

Sto accettando questa risposta poiché spiega perché awk sta eseguendo il buffering completo nel mio esempio, anziché il buffering di linea - controlla se l'input è un tty così come l'output. Ho solo pensato che avrebbe controllato l'output.
Daniel Näslund

@ jw013: grazie per aver cercato lo standard. Per me, volevo solo capire perché Awk stava eseguendo il buffering completo e penso di farlo ora.
Daniel Näslund,

@dannas Posso confermare che -W interactiveè almeno supportato nella distribuzione Ubuntu 12.04 (e presumibilmente più recente) di awk, che è mawk.
Jason C,

37

So che è una vecchia domanda, ma un one-liner può aiutare coloro che vengono qui a cercare:

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

system("")fa il trucco ed è conforme a POSIX. Sistemi non posix: attenzione.

Esiste una funzione più specifica fflush()che fa lo stesso, ma non è disponibile nelle versioni precedenti di awk.

Un'importante informazione dai documenti riguardanti l'uso di system(""):

gawk considera questo uso della funzione system () come un caso speciale ed è abbastanza intelligente da non eseguire una shell (o un altro interprete di comandi) con il comando vuoto. Pertanto, con gawk, questo idioma non è solo utile, ma è anche efficiente.


Questo ha funzionato per me
redolent il

3
Il mio awknon fa nulla su nessuno dei due fflush(), né system(""). L'ho gawkonorato però.
Krzysztof Jabłoński,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.