Wie kann man eine Datei mit awk dauerhaft ändern? ("In-Place" -Bearbeitungen wie bei "sed -i")

10

Ich habe eine awk-Datei 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 diese Datei in der Shell auf

awk new.awk sample.csv

Aber ich kann die Änderungen im Terminal sehen, aber wie man die Änderung dauerhaft in der Datei macht, wie mit -i in sed.

mittu
quelle

Antworten:

16

GNU awk(häufig auf Linux-Systemen zu finden) kann seit Version 4.1.0 eine " awkQuellbibliothek" mit -ioder --includein der Befehlszeile enthalten. Eine der Quellbibliotheken, die mit GNU verteilt awkwird, heißt inplace:

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

Wie Sie sehen können, ersetzt die Ausgabe des awkCodes die Eingabedatei. Das Zeilenspruch therewird nicht beibehalten, da es nicht vom Programm ausgegeben wird.

Mit einem awkSkript in einer Datei würden Sie es gerne verwenden

awk -i inplace -f script.awk datafile

Wenn die awkVariable INPLACE_SUFFIXauf eine Zeichenfolge festgelegt 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 einer Datei (oder einer Reihe von Dateien) jedoch deaktivieren, indem Sie inplace=0in der Befehlszeile vor dieser Datei Folgendes verwenden:

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

Im obigen Befehl file3würde nicht direkt bearbeitet.


Verwenden Sie für eine portablere "In-Place-Bearbeitung" einer einzelnen Datei

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

Dies würde die Eingabedatei an einen temporären Speicherort kopieren und dann den awkCode auf die temporäre Datei anwenden, während auf den ursprünglichen Dateinamen umgeleitet wird.

Durch Ausführen der Vorgänge in dieser Reihenfolge (Ausführen awkin der temporären Datei, nicht in der Originaldatei) wird sichergestellt, dass die Datei-Metadaten (Berechtigungen und Besitz) der Originaldatei nicht geändert werden.

Kusalananda
quelle
4

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.
msp9011
quelle
1
Wenn Sie sich den awk inplace- Quellcode ansehen , ist dies genau das, was er tut: Erstellt eine temporäre Datei, leitet stdout dort um und benennt sie am Ende in die Eingabedatei um.
chx