Dlaczego awk wykonuje pełne buforowanie podczas odczytu z potoku


23

Czytam z portu szeregowego podłączonego do urządzenia GPS wysyłającego ciągi nmea.

Uproszczone wywołanie ilustrujące mój punkt widzenia:

  $ 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

Jeśli zamiast tego spróbuję odczytać z potoku, awk buforuje dane wejściowe przed wysłaniem ich na standardowe wyjście.

$ 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

Jak mogę uniknąć buforowania?

Edycja : Kyle Jones zasugerował, że kot buforuje dane wyjściowe, ale wydaje się, że tak się nie dzieje:

$ 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

Kiedy o tym myślę: pomyślałem, że program używał buforowania linii podczas pisania do terminala i „regularnego buforowania” dla wszystkich innych przypadków. Dlaczego więc kot nie buforuje więcej? Czy port szeregowy sygnalizuje EOF? Dlaczego więc kot nie jest rozwiązany?


1
BashFAQ 009 może być przydatny.
jw013

@ jw013: Dzięki za link, świetne podsumowanie działania buforowania w bash.
Daniel Näslund,

Odpowiedzi:


10

Prawdopodobnie buforuje się w awk, a nie w cat. W pierwszym przypadku awk uważa, że ​​jest interaktywny, ponieważ jego dane wejściowe i wyjściowe to TTY (chociaż są to różne TTY - domyślam się, że awk tego nie sprawdza). W drugim wejściu jest potok, więc działa on nieinteraktywnie.

Musisz jawnie opróżnić program awk. Nie jest to jednak przenośne.

Więcej informacji i szczegółowe informacje na temat opróżniania danych wyjściowych można znaleźć : http://www.gnu.org/software/gawk/manual/html_node/I_002fO-Functions.html


6
Dziękuję za wyjaśnienie. awk -W interactive '{print $0}'wydaje się załatwić sprawę. 'W interactiveOpcja jest dostępna na mojej wersji awk (mawk 1,2), ale nie wiem, czy jest to opcja standardowa.
Daniel Näslund,

1
@ Danny -Wnie jest w standardzie POSIX dlaawk . Nie jestem pewien, co zrobić, jeśli potrzebujesz maksymalnej przenośności.
jw013

Akceptuję tę odpowiedź, ponieważ wyjaśnia, dlaczego awk robi w moim przykładzie pełne buforowanie zamiast buforowania linii - sprawdza, czy wejście jest tty, a także wyjście. Myślałem tylko, że sprawdzi wyjście.
Daniel Näslund,

@ jw013: Dziękujemy za sprawdzenie standardu. Dla mnie chciałem tylko zrozumieć, dlaczego awk robi pełne buforowanie i myślę, że teraz.
Daniel Näslund,

@ Danny Mogę potwierdzić, że -W interactivejest co najmniej obsługiwany w dystrybucji awk Ubuntu 12.04 (i prawdopodobnie nowszej), która jest mawk.
Jason C

37

Wiem, że to stare pytanie, ale linijka może pomóc tym, którzy tu przychodzą, szukając:

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

system("")robi lewę i jest zgodny z POSIX. Systemy inne niż posix: uważaj.

Istnieje bardziej szczegółowa funkcja, fflush()która robi to samo, ale nie jest dostępna w starszych wersjach awk.

Ważna informacja z dokumentów na temat korzystania z system(""):

gawk traktuje to użycie funkcji system () jako szczególny przypadek i jest wystarczająco inteligentny, aby nie uruchamiać powłoki (lub innego interpretera poleceń) z pustym poleceniem. Dlatego w gawk ten idiom jest nie tylko użyteczny, ale także wydajny.


To zadziałało dla mnie
ponury

3
Mój awknic nie robi ani na, fflush()ani na system(""). Mój gawkto zaszczycony.
Krzysztof Jabłoński
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.