Jag har följande awk
skript som tar följande inmatningsfil, input.txt
och producerar utdata nedan. Kan någon ta sig tid att bryta ner hur detta awk
-skript fungerar? Jag har spenderat lite tid på det och det ger inte mycket mening.
Ingång:
$ 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**
Utgång:
RSYNCJOBNA|0021|20140502|10:02:15|10:56:42|0:54:27|FINISHED RSYNCJOBNA|0022|20140502|15:31:06| |0:06:04|INITIATED
Kommando för att få ovanstående utgång:
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
Min uppfattning är att /FINISHED|INITIATED/ {}
betyder att kommandona inuti de lockiga hakparenteserna endast körs på rader som matchar antingen FINISHED
eller INITIATED
men som såvitt jag kan se från utdata verkar manuset tolkas från alla rader. Vad händer?
Kommentarer
Svar
Funktionen getline
läser nästa rad och flyttar skriptet till det. på varandra följande getline
samtal flyttas till nästa rad. Detta är kanske lättare att förstå med ett exempel:
$ cat input.txt foo 1 2 $ awk "/foo/{print; getline; print; getline; print}" input.txt foo 1 2
Som du kan se ovan kommer skriptet att behandla den första raden eftersom den matchar foo
. Varje samtal till getline
läser raden efter den aktuella, så de efterföljande print
samtalen skriver ut nästa rader.
Svar
Om du inte vet vad en awk
-funktion gör är den vanliga strategin för att titta på mansidan:
getline
Ställ in $ 0 från nästa ingångspost; ställ in NF, NR, FNR, RT
Kommandoblocket körs verkligen bara två gånger. De andra raderna hanteras via getline
inifrån block.
Detta kan skrivas om till:
/FINISHED|INITIATED/ { status = $1; line_number=0; next; } { line_number++; } line_number==1 { jobname = $1; } line_number==2 { sequence = $2; date = $1; } ...
Kommentarer
- Vad händer om nästa post är tom?
- @AvinashRaj Varken din kod eller mitt alternativ tittar på raden (med undantag för
/FINISHED|INITIATED/
Raderna räknas bara ner. Uppgifterna måste ordnas exakt (från en awk parsi ng perspektiv) på det sätt du har visat annars kommer koden att brytas.
/FINISHED|INITIATED/
söker awk efter motsvarande rad och gör bara operationen på den aktuella raden. Men operationen utfördes på alla rader. Hur?