Ik heb dit volgende awk
script dat het volgende invoerbestand accepteert, input.txt
en produceert de onderstaande uitvoer. Kan iemand alsjeblieft de tijd nemen om uit te zoeken hoe dit awk
script werkt? Ik “heb er een beetje tijd aan besteed en het slaat nergens op.
Invoer:
$ 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**
Uitvoer:
RSYNCJOBNA|0021|20140502|10:02:15|10:56:42|0:54:27|FINISHED RSYNCJOBNA|0022|20140502|15:31:06| |0:06:04|INITIATED
Commando om de bovenstaande output te krijgen:
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
Ik heb begrepen dat /FINISHED|INITIATED/ {}
betekent dat de opdrachten binnen de accolades alleen worden uitgevoerd op regels die overeenkomen met FINISHED
of INITIATED
maar als voor zover ik aan de uitvoer kan zien, lijkt het script te parseren vanuit alle regels. Wat is er aan de hand?
Reacties
Answer
De functie getline
leest de volgende regel en verplaatst het script ernaar. opeenvolgende getline
oproepen gaan naar de volgende regel. Dit is misschien gemakkelijker te begrijpen met een voorbeeld:
$ cat input.txt foo 1 2 $ awk "/foo/{print; getline; print; getline; print}" input.txt foo 1 2
Zoals zoals je hierboven kunt zien, zal het script de eerste regel verwerken omdat het overeenkomt met foo
. Elke aanroep naar getline
leest de regel na de huidige, dus de volgende print
aanroepen drukken de volgende regels af.
Antwoord
Als u “niet weet wat een awk
-functie doet, dan is de gebruikelijke strategie om de man-pagina te bekijken:
getline
Stel $ 0 in vanaf het volgende invoerrecord; stel NF, NR, FNR in, RT
Het opdrachtblok wordt inderdaad slechts twee keer uitgevoerd. De andere regels worden afgehandeld via getline
vanuit de block.
Dit kan worden herschreven naar:
/FINISHED|INITIATED/ { status = $1; line_number=0; next; } { line_number++; } line_number==1 { jobname = $1; } line_number==2 { sequence = $2; date = $1; } ...
Reacties
- Wat gebeurt er als het volgende record leeg is?
- @AvinashRaj Noch uw code, noch mijn alternatief kijkt naar de inhoud van de regels (met uitzondering van
/FINISHED|INITIATED/
) De regels worden gewoon afgeteld De gegevens moeten exact worden gerangschikt (vanuit een awk parsi ng perspectief) op de manier die je hebt getoond, anders zal de code breken.
/FINISHED|INITIATED/
geven, zoekt awk naar de corresponderende regel en voert de bewerking alleen uit op die bepaalde regel. Maar de bewerking werd op alle regels uitgevoerd. Hoe?