Mengapa awk melakukan buffering penuh saat membaca dari sebuah pipa

23

Saya membaca dari port serial yang terhubung ke perangkat gps yang mengirimkan string nmea.

Doa yang disederhanakan untuk mengilustrasikan poin saya:

  $ 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

Jika saya mencoba membaca dari sebuah pipa, awk buffer input sebelum mengirimnya ke 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

Bagaimana saya bisa menghindari buffering?

Sunting : Kyle Jones menyarankan agar kucing menahan outputnya tetapi itu tampaknya tidak terjadi:

$ 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

Ketika saya memikirkannya: Saya berpikir bahwa sebuah program menggunakan penyangga baris saat menulis ke terminal dan "penyangga biasa" untuk semua kasus lainnya. Lalu, mengapa kucing tidak buffering lebih? Apakah port serial memberi sinyal EOF? Lalu mengapa kucing tidak diberhentikan?

Daniel Näslund
sumber
1
BashFAQ 009 semoga bermanfaat.
jw013
@ jw013: Terima kasih atas tautannya, jumlah yang bagus tentang bagaimana buffering bekerja di bash.
Daniel Näslund

Jawaban:

10

Kemungkinan buffering dalam awk, bukan kucing. Dalam kasus pertama, awk percaya ini interaktif karena input dan outputnya adalah TTYs (walaupun mereka TTYs yang berbeda - saya kira awk tidak memeriksa itu). Yang kedua, input adalah pipa sehingga berjalan non-interaktif.

Anda perlu menyiram secara eksplisit dalam program awk Anda. Ini tidak portabel, meskipun.

Untuk latar belakang dan detail lebih lanjut tentang cara flush output, baca: http://www.gnu.org/software/gawk/manual/html_node/I_002fO-Functions.html

camh
sumber
6
Terima kasih untuk penjelasannya. awk -W interactive '{print $0}'tampaknya melakukan trik. The 'W interactivepilihan tersedia pada versi awk saya (mawk 1.2) tapi aku tak tahu apakah itu pilihan standar.
Daniel Näslund
1
@dannas -Wtidak dalam standar POSIX untukawk . Saya tidak yakin apa yang harus dilakukan jika Anda membutuhkan portabilitas maksimum.
jw013
Saya menerima jawaban ini karena menjelaskan mengapa awk melakukan buffering penuh dalam contoh saya, alih-alih line buffering - memeriksa apakah inputnya tty dan juga output. Saya hanya berpikir bahwa itu akan memeriksa output.
Daniel Näslund
@ jw013: Terima kasih telah mencari standar. Bagi saya, saya hanya ingin mengerti mengapa awk melakukan buffering penuh dan saya pikir saya lakukan sekarang.
Daniel Näslund
@dannas Saya dapat mengkonfirmasi bahwa -W interactivesetidaknya didukung dalam distribusi Ubuntu 12,04 (dan mungkin lebih baru) dari awk, yang merupakan mawk.
Jason C
37

Saya tahu ini adalah pertanyaan lama, tetapi satu kalimat dapat membantu mereka yang datang ke sini mencari:

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

system("")melakukan trik, dan POSIX compliant. Sistem non-posix: waspadalah.

Ada fungsi fflush()yang lebih spesifik yang melakukan hal yang sama, tetapi tidak tersedia dalam versi awk yang lebih lama.

Sepotong informasi penting dari dokumen mengenai penggunaan system(""):

gawk memperlakukan penggunaan fungsi system () ini sebagai kasus khusus dan cukup pintar untuk tidak menjalankan shell (atau penerjemah perintah lainnya) dengan perintah kosong. Oleh karena itu, dengan gawk, idiom ini tidak hanya berguna, tetapi juga efisien.

Shrein
sumber
Ini bekerja untuk saya
harum
3
Saya awktidak melakukan apa-apa pada tidak fflush()atau system(""). Saya gawkmenghargainya.
Krzysztof Jabłoński