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
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