Jeg har dette følgende awk
script, der tager følgende inputfil, input.txt
og producerer output nedenfor. Kan nogen tage sig tid til at nedbryde, hvordan dette awk
script fungerer? Jeg har brugt lidt tid på det, og det giver ikke meget mening.
Input:
$ 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**
Output:
RSYNCJOBNA|0021|20140502|10:02:15|10:56:42|0:54:27|FINISHED RSYNCJOBNA|0022|20140502|15:31:06| |0:06:04|INITIATED
Kommando for at få ovenstående udgang:
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 forståelse er, at /FINISHED|INITIATED/ {}
betyder, at kommandoerne inde i de krøllede seler kun køres på linjer, der matcher enten FINISHED
eller INITIATED
men som så vidt jeg kan se fra output, ser scriptet ud til at parses fra alle linjer. Hvad sker der?
Kommentarer
Svar
Funktionen getline
læser den næste linje og flytter scriptet til det. fortløbende getline
opkald flytter til næste linje. Dette er måske lettere at forstå med et eksempel:
$ cat input.txt foo 1 2 $ awk "/foo/{print; getline; print; getline; print}" input.txt foo 1 2
Som du kan se ovenfor, behandler scriptet den første linje, fordi det matcher foo
. Hvert opkald til getline
læser linjen efter den aktuelle, så de efterfølgende print
opkald udskriver de næste linjer.
Svar
Hvis du ikke ved hvad en awk
-funktion gør, er den sædvanlige strategi for at se på mandsiden:
getline
Indstil $ 0 fra næste input-post; indstil NF, NR, FNR, RT
Kommandoblokken udføres faktisk kun to gange. De øvrige linjer håndteres via getline
inden for blok.
Dette kunne omskrives til:
/FINISHED|INITIATED/ { status = $1; line_number=0; next; } { line_number++; } line_number==1 { jobname = $1; } line_number==2 { sequence = $2; date = $1; } ...
Kommentarer
- Hvad sker der, hvis den næste post er tom?
- @AvinashRaj Hverken din kode eller mit alternativ ser på linjernes indhold (med undtagelse af
/FINISHED|INITIATED/
Linjerne tælles bare ned. Dataene skal arrangeres nøjagtigt (fra en awk parsi ng perspektiv) på den måde, du har vist, ellers vil koden bryde.
/FINISHED|INITIATED/
, søger awk efter den tilsvarende linje og udfører kun operationen på den pågældende linje. Men operationen blev udført på alle linjerne. Hvordan?