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?