Wie füge ich der Ausgabe eines Awk-Befehls nachträglich einen Header hinzu?

Wie füge ich der Ausgabe eines Awk-Befehls nachträglich einen Header hinzu?

Ich erstelle mit awk eine Datei (Ausgabe) aus einer anderen Datei (Eingabe) (unter Überspringung des Headers):

awk 'NR==1{next} $3==1 {print $1"\t"$2}' input > output

Dann habe ich erst im Nachhinein berechenbare Header-Informationen, die ich per sed einfüge:

sed -i "1s/^/head1\thead2\n/" output

Allerdings ist der sed ziemlich langsam. Ich frage mich, ob es dafür eine bessere Möglichkeit gibt. Zum Beispiel das Speichern des Awk-Ergebnisses und anschließendes Schreiben der Datei, nachdem ich die Header-Informationen habe?

Antwort1

Wenn Sie den Body in der outputDatei haben und den gewünschten Header in einer Datei mit dem Namen header( printf "head1\thead2\n" > header), dann können Sie den Header wie folgt einfügen:

ed -s output <<< $'0r header\nw\nq'

Das -sweist darauf hin, dass die Diagnoseausgabe unterdrückt werden soll (also wie viele Bytes es von eingelesen hat output, wie viele Bytes es von eingelesen hat headerund wie viele Bytes es am Ende ausgegeben hat).

Die ed-Befehle sind:

  • 0r header- Lesen Sie in Zeile Null den Inhalt der Dateiheader
  • w- die Datei ausschreiben
  • q- beendet

Antwort2

Versuche es mitSchlag:

echo -e "head1\thead2\n$(cat output)" > /tmp/out && mv /tmp/out output

Antwort3

Ich würde es in Bash machen

{ echo -e "head1\thead2" ; cat output ; } > newoutput

im Vergleich zu RomanPerekhrests Antwort wird es sogar bei sehr langen Dateien einwandfrei funktionieren (seine würde die Datei zuerst in den Speicher laden und dann das Echo ausführen; auch Bash hat meiner Meinung nach eine maximale Eingabelänge)

Antwort4

Nach weiterem Googeln fand ich diese Frage: Ändern Sie den Header in einer großen Datei, ohne die gesamte Datei neu zu schreiben.

Um zu verhindern, dass beim Hinzufügen des Headers die gesamte Datei neu geschrieben werden muss, habe ich beim Erstellen der Datei einen Dummy-Header mit einer Mindestanzahl von Bytes (durch Auffüllen mit Nullen) gedruckt:

awk 'NR==1{print "dummyhead100\tdummyhead20000"; next} $3==1 {print 
$1"\t"$2}' input > output

Ich erstelle dann eine Datei (oder Zeichenfolgenvariable) mit dem neuen Kopf als header.tsv und ersetze den Dummy-Header an Ort und Stelle (nachdem ich sichergestellt habe, dass der Dummy-Header und der neue Header dieselbe Anzahl an Bytes haben) mithilfe von dd:

dd conv=notrunc obs=1 if=header.tsv of=output

Auf diese Weise outputerfolgt die Bearbeitung direkt vor Ort und ich muss nicht warten, bis die gesamte Datei kopiert wurde, oder sie im Speicher behalten.

verwandte Informationen