Ich habe eine Datendatei, die ich awk
basierend auf dem letzten Datenpunkt normalisieren möchte . Daher möchte ich zuerst auf den letzten Datenpunkt zugreifen, die Daten normalisieren und dann normal verarbeiten.
Die folgende Methode, die tac
zweimal verwendet wird, erledigt die Aufgabe, ist jedoch möglicherweise komplizierter als erforderlich.
$ cat file
0 5
1 2
2 3
3 4
$ tac file | awk 'NR==1{norm=$2} {print $1, $2/norm}' | tac
0 1.25
1 0.5
2 0.75
3 1
Meine Frage lautet wie folgt: Ist es möglich, das obige Ergebnis nur mit awk zu erzielen?
Ich denke, die Antwort lautet "Nein, awk scannt die Datei Zeile für Zeile", aber ich bin offen für Vorschläge für Alternativen.
quelle
$ awk --version GNU Awk 3.1.8
. Können Sie vielleicht eine sehr kleine Erklärung hinzufügen, wie zwei Eingabedateien behandelt werden und wasnext
funktioniert?Wenn es sich bei Ihrer Datenquelle um eine Datei handelt, die mehrmals gelesen werden kann (dh es handelt sich nicht um einen Stream), sollten Sie zuerst
tail(1)
die gewünschten Daten aus der letzten Zeile abrufen und diese zur sequentiellen Verarbeitung der Datei an awk übergeben.tail
wird bis zum Ende der Datei versuchen, die letzte Zeile zu lesen, ohne alle Daten davor lesen zu müssen.Dies ist ein großer Gewinn bei großen Dateien, bei denen die gesamte Datei nicht in den Puffercache passt (was bedeutet, dass sie bei jedem Durchgang zweimal von der Festplatte gelesen werden muss), und hilft in geringerem Maße, indem sie nicht gescannt werden muss die Eingabe, um zur letzten Zeile zu gelangen. Kleinere Dateien unterscheiden sich möglicherweise nicht wesentlich von einem Zwei-Pass-Ansatz.
quelle
Sie können sie in ein Array laden und rückwärts lesen:
Sie könnten es effizienter machen, aber diese Art zeigt, warum dies
awk
nicht das richtige Werkzeug ist. Verwenden Sietac
GNU tac, sofern verfügbar, im Allgemeinen das schnellste einer Vielzahl von Tools für diesen Job.quelle
for
-loops inawk
nicht die Lösung ist.