Come modificare un file sul posto usando awk? (come con "sed -i")


11

Ho una awksceneggiatura 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 }

Lo sto chiamando in shell

awk new.awk sample.csv

... ma posso vedere i cambiamenti nel terminale. Come effettuare la modifica sul posto nel file, come quando si utilizza sed -i?

Risposte:


16

GNU awk(comunemente presente sui sistemi Linux), dalla versione 4.1.0, è in grado di includere una " awklibreria sorgente" con -io --includesulla riga di comando. Una delle librerie di origine distribuite con GNU awkè una chiamata inplace:

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

Come puoi vedere, questo fa sì che l'output del awkcodice sostituisca il file di input. La frase dicendo therenon viene mantenuta in quanto non viene emessa dal programma.

Con uno awkscript in un file, lo useresti come

awk -i inplace -f script.awk datafile

Se la awkvariabile INPLACE_SUFFIXè impostata su una stringa, la libreria eseguirà un backup del file originale con quello come suffisso del nome file.

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

Se si dispone di più file di input, ogni file deve essere modificato individualmente sul posto. Ma puoi disattivare la modifica sul posto per un file (o un set di file) utilizzando inplace=0dalla riga di comando prima di quel file:

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

Nel comando sopra, file3non verrebbe modificato sul posto.


Per una "modifica sul posto" più portatile di un singolo file, utilizzare

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

Ciò copierebbe il file di input in un percorso temporaneo, quindi applicherebbe il awkcodice sul file temporaneo durante il reindirizzamento al nome file originale.

L'esecuzione delle operazioni in questo ordine (in esecuzione awksul file temporaneo, non sul file originale) garantisce che i metadati (autorizzazioni e proprietà) del file originale non vengano modificati.


4

Prova questo.

awk  new.awk sample.csv > tmp.csv && mv -f tmp.csv sample.csv
  • reindirizzare l'output su un file temporaneo.
  • quindi spostare il contenuto del file temporaneo nel file originale.

1
Se guardi il codice sorgente di awk inplace , questo è esattamente ciò che fa: crea un file temporaneo, reindirizza lo stdout lì e alla fine lo rinomina nel file di input.
chx,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.