Wie zu erkennen, die Letzte Zeile in awk vor ENDE
Ich versuche, fügen Sie die Letzte Zeile in die Datei, die ich erschaffe. Wie ist es möglich, zu erkennen, die Letzte Zeile einer Datei in awk, bevor END
? Ich muss dies tun, da die Variablen nicht die Arbeit in der END
block,
so versuche ich zu vermeiden, mit END
.
awk ' { do some things..; add a new last line into file;}'
bevor END
, das will ich nicht:
awk 'END{print "something new" >> "newfile.txt"}'
- Die Variablen insbesondere brauchen Sie nicht verfügbar sind in der END-block? Die meisten der Variablen (
NR
,NF
,FNR
usw. ) haben sehr günstigen Werten in der END-block. - die Variablen, die ich brauchen, sind einige lokale Variablen, die spielen die zentrale Rolle bei der Schaffung der Datei.. wie z.B.:
print $0 >> sprintf("%s/%s_%s.txt", user, mode, FILENAME)
dieseuser
undmode
sind nicht verfügbar inEND
werden, die immer den Namen der Datei... - Diese Frage macht keinen Sinn. Awk nicht über lokale Variablen, die anderen als Parameter der Funktion. Wenn Sie ermitteln einen Dateinamen und legen Sie es in
fname
, dannfname
behält seinen Wert solange, bis entweder Awk beendet wird, oder ein neuer Wert zugewiesen wird, infname
. - Wenn Sie die Verarbeitung der Aufzeichnung der Eingangs -, davon ausgehen, dass es könnte der Letzte sein, und berechnen Sie den Namen der Datei, die erforderlich sein wird, in diesem Fall, steckte es in eine variable namens
fname
. Wenn es zu diesem Datensatz ist der Letzte, dann derEND
- block wird ausgeführt, undfname
verfügbar sein wird dann.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Eine Möglichkeit ist die Verwendung
getline
- Funktion, um die Datei zu verarbeiten. Es gibt1
auf Erfolg,0
auf das Ende der Datei und-1
auf einen Fehler.Vorausgesetzt
infile
mit diesen Daten:Ausgabe:
do { ... } while (getline == 1)
, in welchem Fall Sie nicht brauchen, dieprint
Anweisung vor der Schleife.Durch das Lesen dieselbe Datei zweimal ( Empfohlen )
Mit
getline
8 line 8
). Nur die Nachricht.seq 8 > testfile; awk 'BEGIN{while((getline t < ARGV[1]) > 0)last++;close(ARGV[1])}{print $0 ((last==FNR)?" I am Last":"")}' testfile
print ((last==FNR) ? "I am Last: ":"") $0
print $0 (() ? : )
Linie, wie ich vorgeschlagen, um tatsächlich sehen die Linie.print $0 , (() ? : )
wenn Sie möchten, dass andere Trennzeichen incase, wenn Sie so etwas wie-v OFS='|'
habe ich noch Komma im obigen post auch besser Lesen, es gibt eigentlich keine Notwendigkeit, wenn Sie möchten, space als TrennerGNU Awk 4.1.4, API: 1.1 (GNU MPFR 3.1.5-p2, GNU MP 6.1.2)
. Ich habe nicht ändern die Standard -OFS
. Hinzufügen ein Komma funktioniert nicht für mich.awk 'FNR==NR{last++;next}{print $0, ((last==FNR)?"I am Last":"")}' file file
yourcommand | awk '{ } '
ich leider nicht haben, cygwin zu testen, hast du vergessen zu geben-input-Datei zweimal durch Zufall ?RS
variable oder"\n"
würde wie folgt Aussehenprint $0 RS (() ? : )
print $0 ((last==FNR) ? "\nI am Last" : "")
(natürlich druckt es die Nachricht in die nächste Zeile, aber Sie bekommen zu sehen, die Letzte Eingabezeile).Können Sie
ENDFILE
ist, führt er vorEND
:ENDFILE existiert in der neuesten version von awk (>4.0 glaube ich).
Drucken der vorherigen Zeile.
Wenn die aktuelle Zeile 2, Zeile drucken 1,
wenn die aktuelle Zeile 3, Zeile drucken 2.
....
bis Ende
description
, die zu erklären hilft, Ihren code. DankKönnen Sie die Anzahl der Zeilen in einer Datei mit
"wc -l" | getline filesize
in der begin-block und verwenden SieNR == filesize
zu testen, die Letzte Zeile in dem Skript Körper.\landscape
wc
-basierte pipeline-Befehl funktioniert nur mitstdin
input-aufgrund fehlender expliziter input - was ist eine catch-22: der Befehl Auspuff stdin input, wodurch die nachfolgenden Blöcke in das awk-Programm haben keinen Eingang Links. Um diesen Ansatz verwenden, (a) sicherzustellen, dass eine tatsächliche Dateiname angegeben wurde und (b) finden Sie explizit:"wc -l < \""ARGV[1]"\"" | getline lineCount; lineCount+=0
(DielineCount+=0
Teil ist für Plattformen wie OSX, wowc -l
Ausgänge führende whitespace-Zeichen, es garantiert, dass awk behandeltlineCount
als eine Nummer.)rewind()
Funktion mit einer unbestimmten (D. H., Daten-abhängig) Anzahl der Wiederholungen. Also, statt ungeschickt mitgetline
ich test für die EOF-wie Sie hier vorgeschlagen wird.Weiß ich die Antwort wurde angenommen, aber es ist einfach falsch.
Weil Sie wollen, zu verwenden awk als parser und nicht als code.
Awk sollte verwendet werden, innerhalb von einigen unix-pipes und es sollte nicht verwendet werden, innerhalb jeder Logik.
Ich hatte das gleiche problem und ich löste es, innerhalb von awk wie diese:
zzeile=
wc -l <file>
cat | awk -v nl=${zzeile} '{if (nl != NR) {print $0,",","\";} else {print;}}' >> ${someout}
Gibt es hier einen wichtigen Punkt: Rohre, Unterputz -, und RAM.
Wenn Sie awk ausspucken seiner Ausgabe können Sie Weiterreichen an den nächsten Prozessor.
Wenn Sie getline, und insbesondere innerhalb einer Schleife, die Sie vielleicht nicht sehen, das Ende.
getline sollte verwendet werden, nur für eine Zeile und eine eventuelle Abhängigkeit auf die nächste Zeile.
Ich Liebe awk, aber wir können nicht alles mit!!!
BEARBEITET:
Für wen down-stimmten die Antwort, ich will einfach nur, um dieses Skript:
Und natürlich die ersten Ergebnisse:
Wo Sie sparen etwa 10% der Zeit, nur weil der getline.
Betrachten Sie diese innerhalb komplexer Logik und bekommen Sie vielleicht auch ein " worst Bild. In dieser einfachen version, Speicher-Betrachtung nicht berücksichtigt.
Und scheint Sie nicht spielen eine Rolle für diese einfache version. Aber der Speicher könnte auch eine Rolle spielen, wenn Sie in komplexere Logik ...
Natürlich versuchen, es auf Ihrem Computer.
Dies ist der Grund, warum ich vorschlug, andere Optionen zu erwägen, im Allgemeinen.
wc
stattgetline
, aber ich habe zwei kleine Spitzfindigkeiten. Erstens, nutzennlines=$(wc -l < filename)
(beachten Sie die Umleitung von stdin), so dass zzeile nicht so aussieht:80 filename
. Zweitens, ich glaube nicht, dass dein benchmark ist gültig. Inx.r
sollten Sie in der Zeit, die es braucht, um diewc
und der test fürFNR==nlines
. Meine Vermutung ist, dass die getline-Lösung ist eigentlich schneller, weil Sie nur die Analysefilename
einmal.