web-dev-qa-db-fra.com

Enregistrer les modifications en place avec awk

J'apprends awk et j'aimerais savoir s'il existe une option pour écrire les modifications dans le fichier, comme pour sed où j'utiliserais -i option pour enregistrer les modifications dans un fichier.

Je comprends que je pourrais utiliser la redirection pour écrire les modifications. Cependant, y a-t-il une option dans awk pour le faire?

114
Deano

Au plus tard GNU Awk (depuis 4.1.0 publié ), il a l'option de édition du fichier "inplace" :

[...] L'extension "inplace", construite à l'aide de la nouvelle installation, peut être utilisée pour simuler GNU "sed -i" fonctionnalité. [...]

Exemple d'utilisation:

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

Pour conserver la sauvegarde:

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

Sauf si vous avez GNU awk 4.1.0 ou version ultérieure ...

Vous n'aurez pas une telle option comme sed's -i option alors faites plutôt:

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

Noter la -i n'est pas magique, il crée également un fichier temporaire sed le gère simplement pour vous.


À partir de GNU awk 4.1.0 ...

GNU awk a ajouté cette fonctionnalité dans la version 4.1.0 (publiée le 10/05/2013). Ce n'est pas aussi simple que de simplement donner le -i option décrite dans les notes publiées:

La nouvelle option -i (de xgawk) est utilisée pour charger les fichiers de la bibliothèque awk. Cela diffère de -f en ce que le premier argument sans option est traité comme un script.

Vous devez utiliser le paquetage inplace.awkinclure un fichier pour appeler l’extension correctement, comme ceci:

$ cat file
123 abc
456 def
789 hij

$ gawk -i inplace '{print $1}' file

$ cat file
123
456
789

La variable INPLACE_SUFFIX peut être utilisé pour spécifier l’extension d’un fichier de sauvegarde:

$ gawk -i inplace -v INPLACE_SUFFIX=.bak '{print $1}' file

$ cat file
123
456
789

$ cat file.bak
123 abc
456 def
789 hij

Je suis heureux que cette fonctionnalité ait été ajoutée, mais pour moi, la mise en oeuvre n'est pas très bizarre car le pouvoir vient de la concision du langage et du -i inplace est 8 caractères trop long i.m.o.

Voici un lien vers le manuel pour le mot officiel.

117
Chris Seymour

@ Sudo_O a le droit réponse .

Cela ne peut pas marcher:

someprocess < file > file

Le shell effectue les redirections avant que ne confie le contrôle à un processus ( redirections ). Le > _ la redirection tronquera le fichier à une taille nulle ( redirection de la sortie ). Par conséquent, au moment où un processus est lancé et veut lire le fichier, il n’ya aucune donnée à lire.

12
glenn jackman

Une alternative consiste à utiliser sponge:

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

Où vous remplacez '{print $0}' par votre script awk et your_file par le nom du fichier que vous souhaitez modifier à la place.

sponge absorbe entièrement l'entrée avant de l'enregistrer dans le fichier.

11
Codoscope

juste un petit bidouillage qui fonctionne

echo "$(awk '{awk code}' file)" > file
11
Yuri G.

suivre ne fonctionnera pas

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

cela devrait fonctionner

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

En utilisant tee

 awk '{awk code}' file | tee file

la commande tee a lieu et est exécutée après la commande awk en raison de la commande |.

4
shaiki siegal

Si vous voulez une solution awk-only sans créer de fichier temporaire et utilisable avec version! = (Gawk 4.1.0):

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