awk salva le modifiche sul posto

Sto imparando awk e vorrei sapere se c’è un’opzione per scrivere modifiche al file, simile a sed dove userò l’opzione -i per salvare le modifiche in un file.

Capisco che potrei usare il reindirizzamento per scrivere cambiamenti. Tuttavia esiste un’opzione in awk per farlo?

Nell’ultimo GNU Awk (dalla versione 4.1.0 rilasciata ), ha la possibilità di modificare il file “inplace” :

[…] L’estensione “inplace”, costruita utilizzando la nuova funzione, può essere utilizzata per simulare la funzione GNU ” sed -i “. […]

Esempio di utilizzo:

 $ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1 file2 file3 

Per mantenere il backup:

 $ gawk -i inplace -v INPLACE_SUFFIX=.bak '{ gsub(/foo/, "bar") } > { print }' file1 file2 file3 

A meno che non si abbia GNU awk 4.1.0 o successivo …

Non avrai un’opzione simile all’opzione -s di sed quindi preferisci:

 $ awk '{print $0}' file > tmp && mv tmp file 

Nota: il -i non è magico, sta anche creando un file temporaneo sed semplicemente lo gestisce per te.


A partire da GNU awk 4.1.0 …

GNU awk aggiunto questa funzionalità nella versione 4.1.0 (rilasciata il 10/05/2013) . Non è così semplice come dare l’opzione -i come descritto nelle note rilasciate:

La nuova opzione -i (da xgawk) viene utilizzata per caricare i file di libreria awk. Questo differisce da -f in quanto il primo argomento non opzionale viene trattato come uno script.

È necessario utilizzare il file inplace.awk fornito in bundle per richiamare correttamente l’estensione in questo modo:

 $ cat file 123 abc 456 def 789 hij $ gawk -i inplace '{print $1}' file $ cat file 123 456 789 

La variabile INPLACE_SUFFIX può essere utilizzata per specificare l’estensione per un file di backup:

 $ gawk -i inplace -v INPLACE_SUFFIX=.bak '{print $1}' file $ cat file 123 456 789 $ cat file.bak 123 abc 456 def 789 hij 

Sono felice che questa funzione sia stata aggiunta, ma per me l’implementazione non è molto imbarazzante in quanto il potere è con la concisione del linguaggio e -i inplace è di 8 caratteri per IMO lungo.

Ecco un link al manuale per la parola ufficiale.

@sudo_O ha la risposta giusta.

Questo non può funzionare:

 someprocess < file > file 

La shell esegue i reindirizzamenti prima di passare il controllo a un processo ( reindirizzamenti ). Il reindirizzamento troncerà il file alla dimensione zero ( reindirizzamento dell’output ). Pertanto, quando alcuni processi vengono avviati e vogliono leggere dal file, non ci sono dati da leggere.

solo un piccolo trucco che funziona

 echo "$(awk '{awk code}' file)" > file 

Un’alternativa è usare la sponge :

 awk '{print $0}' your_file | sponge your_file 

Dove sostituisci '{print $0}' dal tuo script awk e your_file dal nome del file che vuoi modificare in posizione.

sponge assorbe interamente l’input prima di salvarlo nel file.

seguire non funzionerà

 echo $(awk '{awk code}' file) > file 

questo dovrebbe funzionare

 echo "$(awk '{awk code}' file)" > file 

Usando il tee

  awk '{awk code}' file | tee file 

il comando tee luogo ed eseguito dopo che il comando awk è terminato a causa del | .

Nel caso in cui si desideri una soluzione awk-only senza creare un file temporaneo e utilizzabile con la versione! = (Gawk 4.1.0):

 awk '{a[b++]=$0} END {for(c=0;c<=b;c++)print a[c]>ARGV[1]}' file