Am următorul script awk
care ia următorul fișier de intrare, input.txt
și produce rezultatul de mai jos. Poate cineva să-și ia timp să descrie cum funcționează acest script awk
? „Am petrecut puțin timp pe el și nu are prea mult sens.
Intrare:
$ 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**
Ieșire:
RSYNCJOBNA|0021|20140502|10:02:15|10:56:42|0:54:27|FINISHED RSYNCJOBNA|0022|20140502|15:31:06| |0:06:04|INITIATED
Comandă pentru obținerea rezultatului de mai sus:
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
Înțelegerea mea este că /FINISHED|INITIATED/ {}
înseamnă că comenzile din interiorul acoladelor vor fi executate numai pe linii care se potrivesc fie cu FINISHED
, fie cu INITIATED
din câte îmi dau seama din rezultat, scriptul pare să analizeze din toate liniile. Ce se întâmplă?
Comentarii
Răspuns
Funcția getline
citește următoarea linie și mută scriptul către acesta. Deci, apelurile consecutive getline
trec la următoarea linie. Acest lucru este probabil mai ușor de înțeles cu un exemplu:
$ cat input.txt foo 1 2 $ awk "/foo/{print; getline; print; getline; print}" input.txt foo 1 2
puteți vedea mai sus, scriptul va procesa prima linie, deoarece se potrivește cu foo
. Fiecare apel către getline
va citi linia după cea curentă, astfel încât apelurile print
ulterioare imprimă următoarele linii.
Răspuns
Dacă nu știți ce face o funcție awk
atunci strategia obișnuită este pentru a arunca o privire asupra paginii man:
getline
Setați 0 $ din următoarea înregistrare de intrare; setați NF, NR, FNR, RT
Blocul de comandă este într-adevăr executat doar de două ori. Celelalte linii sunt tratate prin getline
din interiorul bloc.
Acest lucru ar putea fi rescris în:
/FINISHED|INITIATED/ { status = $1; line_number=0; next; } { line_number++; } line_number==1 { jobname = $1; } line_number==2 { sequence = $2; date = $1; } ...
Comentarii
- Ce se întâmplă dacă următoarea înregistrare este goală?
- @AvinashRaj Nici codul dvs., nici alternativa mea nu privesc conținutul liniilor (cu excepția
/FINISHED|INITIATED/
Liniile sunt doar numărate în jos. Datele trebuie să fie aranjate exact (dintr-un parsi awk ng perspective) în modul în care ați arătat altfel, codul se va sparge.
/FINISHED|INITIATED/
, awk caută linia corespunzătoare și efectuați operația numai pe acea linie specială. Dar operațiunea a fost efectuată pe toate liniile. Cum?