Mam następujący awk
skrypt, który przyjmuje następujący plik wejściowy, input.txt
i generuje poniższe dane wyjściowe. Czy ktoś może poświęcić trochę czasu na wyjaśnienie, jak działa ten skrypt awk
? Spędziłem nad tym trochę czasu i nie ma to większego sensu.
Dane wejściowe:
$ cat input.txt
FINISHED RSYNCJOBNA 20140502 0021 2182096 2082096 6 5 2014820905820902 10:02:15 2014820905820902 10:56:42 0:54:27 INITIATED RSYNCJOBNA 20140502 0022 3282096 3182096 6 5 2014820905820902 15:31:06 0:06:04 ce eque**
Wyjście:
RSYNCJOBNA|0021|20140502|10:02:15|10:56:42|0:54:27|FINISHED RSYNCJOBNA|0022|20140502|15:31:06| |0:06:04|INITIATED
Polecenie uzyskania powyższego wyniku:
awk -v OFS="|" "/FINISHED|INITIATED/ { status = $1; getline; jobname = $1; getline; sequence = $2; date = $1; getline; start = $2; getline; if (status == "FINISHED") { end = $2; getline } else { end = " " } runtime = $1; print jobname, sequence, date, start, end, runtime, status; }" input.txt
Rozumiem, że /FINISHED|INITIATED/ {}
oznacza, że polecenia wewnątrz nawiasów klamrowych będą wykonywane tylko w wierszach pasujących do FINISHED
lub INITIATED
, ale jako o ile mogę stwierdzić z danych wyjściowych, skrypt wydaje się analizować ze wszystkich wierszy. Co się dzieje?
Komentarze
Odpowiedź
Funkcja getline
odczytuje następną linię i przenosi do niej skrypt. kolejne getline
wywołania przechodzą do następnej linii. Być może łatwiej to zrozumieć na przykładzie:
$ cat input.txt foo 1 2 $ awk "/foo/{print; getline; print; getline; print}" input.txt foo 1 2
Jak jak widać powyżej, skrypt przetworzy pierwszą linię, ponieważ pasuje ona do foo
. Każde wywołanie getline
spowoduje odczytanie wiersza następującego po bieżącej, więc kolejne wywołania print
powodują wypisanie kolejnych wierszy.
Odpowiedź
Jeśli nie wiesz, co robi funkcja awk
, wówczas zwykłą strategią jest aby rzucić okiem na stronę podręcznika:
getline
Ustaw $ 0 z następnego rekordu wejściowego; ustaw NF, NR, FNR, RT
Blok poleceń jest faktycznie wykonywany tylko dwukrotnie. Pozostałe wiersze są obsługiwane przez getline
z poziomu blok.
Można to przepisać na:
/FINISHED|INITIATED/ { status = $1; line_number=0; next; } { line_number++; } line_number==1 { jobname = $1; } line_number==2 { sequence = $2; date = $1; } ...
Komentarze
- Co się stanie, jeśli następny rekord jest pusty?
- @AvinashRaj Ani Twój kod, ani moja alternatywa nie przeglądają zawartości wierszy (z wyjątkiem
/FINISHED|INITIATED/
Linie są po prostu odliczane. Dane muszą być dokładnie ułożone (z pliku awk parsi ng perspektywy) w sposób, który pokazałeś, w przeciwnym razie kod się zepsuje.
/FINISHED|INITIATED/
, awk wyszukuje odpowiednią linię i wykonuje operację tylko na tej konkretnej linii. Ale operacja została wykonana na wszystkich wierszach. Jak?