Wie ändere ich eine Datei direkt mit awk? (wie mit „sed -i“)

Wie ändere ich eine Datei direkt mit awk? (wie mit „sed -i“)

Ich habe ein awkSkript new.awk:

BEGIN { FS = OFS = "," }

NR == 1 {
    for (i = 1; i <= NF; i++)
        f[$i] = i
}

NR > 1 {
    begSecs = mktime(gensub(/[":-]/, " ", "g", $(f["DateTime"])))
    endSecs = begSecs + $(f["TotalDuration"])
    $(f["CallEndTime"]) = strftime("%Y-%m-%d %H:%M:%S", endSecs)
}

{ print }

Ich rufe dies in der Shell auf

awk new.awk sample.csv

... aber ich kann die Änderungen im Terminal sehen. Wie kann ich die Änderung direkt in der Datei vornehmen, wie bei Verwendung von sed -i?

Antwort1

GNU awk(häufig auf Linux-Systemen zu finden) kann seit Version 4.1.0 eine „ awkQuellbibliothek“ mit -ioder --includeauf der Kommandozeile einbinden (sieheWie verwende ich die Option -i oder die Direktive @include von gawk sicher?zusammen mit Stéphanes Kommentar unten zu den damit verbundenen Sicherheitsproblemen). Eine der mit GNU verteilten Quellbibliotheken awkheißt inplace:

$ cat file
hello
there
$ awk -i inplace '/hello/ { print "oh,", $0 }' file
$ cat file
oh, hello

Wie Sie sehen, wird dadurch die Eingabedatei durch die Ausgabe des awkCodes ersetzt. Die Zeile mit dem Inhalt therewird nicht beibehalten, da das Programm sie nicht ausgibt.

Mit einem awkSkript in einer Datei würden Sie es wie folgt verwenden:

awk -i inplace -f script.awk datafile

Wenn die awkVariable INPLACE_SUFFIXauf eine Zeichenfolge gesetzt ist, erstellt die Bibliothek eine Sicherungskopie der Originaldatei mit dieser als Dateinamensuffix.

awk -i inplace -v INPLACE_SUFFIX=.bak -f script.awk datafile

Wenn Sie mehrere Eingabedateien haben, wird jede Datei einzeln direkt bearbeitet. Sie können die direkte Bearbeitung jedoch für eine Datei (oder eine Gruppe von Dateien) deaktivieren, indem Sie inplace=0in der Befehlszeile vor dieser Datei Folgendes eingeben:

awk -i inplace -f script.awk file1 file2 inplace=0 file3 inplace=1 file4

Im obigen Befehl file3würde keine Bearbeitung an Ort und Stelle erfolgen.


Für eine portablere „In-Place-Bearbeitung“ einer einzelnen Datei verwenden Sie

tmpfile=$(mktemp)
cp file "$tmpfile" &&
awk '...some program here...' "$tmpfile" >file
rm "$tmpfile"

Dadurch wird die Eingabedatei an einen temporären Speicherort kopiert und der awkCode anschließend auf die temporäre Datei angewendet, während eine Umleitung zum ursprünglichen Dateinamen erfolgt.

Durch das Ausführen der Vorgänge in dieser Reihenfolge (Ausführen awkauf der temporären Datei, nicht auf der Originaldatei) wird sichergestellt, dass die Dateimetadaten (Berechtigungen und Eigentumsrechte) der Originaldatei nicht geändert werden.

Antwort2

Versuche dies.

awk  new.awk sample.csv > tmp.csv && mv -f tmp.csv sample.csv
  • Leiten Sie die Ausgabe in eine temporäre Datei um.
  • Verschieben Sie dann den Inhalt der temporären Datei in die Originaldatei.

verwandte Informationen