web-dev-qa-db-fra.com

comment écrire la recherche dans le même fichier en utilisant la commande awk

awk '/^nameserver/ && !modif { printf("nameserver 127.0.0.1\n"); modif=1 } {print}' testfile.txt

Il affiche la sortie mais je veux écrire la sortie dans le même fichier. Dans mon exemple testfile.txt.

25
Venkat

Pas possible en soi. Vous avez besoin d'un deuxième fichier temporaire, car vous ne pouvez pas lire et écraser le même fichier. Quelque chose comme:

awk '(PROGRAM)' testfile.txt > testfile.tmp && mv testfile.tmp testfile.txt

Le programme mktemp est utile pour générer des noms de fichiers temporaires uniques.

Il existe quelques astuces pour éviter un fichier temporaire, mais elles reposent principalement sur la mise en cache et les mémoires tampon de lecture et deviennent rapidement instables pour les fichiers plus volumineux.

41
thiton

Depuis GNU Awk 4.1.0, il existe une extension "inplace", vous pouvez donc:

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

Pour conserver une copie de sauvegarde des fichiers d'origine, essayez ceci:

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

Ceci peut être utilisé pour simuler la fonction GNU sed -i.

Voir: Activation de la modification de fichiers sur place

9
kenorb

Malgré le fait que l'utilisation d'un fichier temporaire soit correcte, je ne l'aime pas parce que:

  • vous devez être sûr de ne pas effacer un autre fichier temporaire (oui, vous pouvez utiliser mktemp - c'est un outil très utile)

  • vous devez prendre soin de le supprimer (ou de le déplacer comme dit thiton), y compris lorsque votre script se bloque ou s’arrête avant la fin (la suppression des fichiers temporaires à la fin du script n’est donc pas sage)

  • il génère IO sur le disque (ok pas tant que ça mais on peut le rendre plus léger)

Donc, ma méthode pour éviter le fichier temporaire est simple:

my_output="$(awk '(PROGRAM)' source_file)"
echo "$my_output" > source_file

Notez l'utilisation de guillemets doubles lorsque vous récupérez le résultat de la commande awk ET lorsque vous utilisez echo (sinon, vous n'aurez pas de saut de ligne).

8
Sylock

Vous pouvez également utiliser sponge de moreutils .

Par exemple

awk '!a[$0]++' file|sponge file

supprime les lignes en double et

 awk '{$2=10*$2}1' file|sponge file

multiplie la deuxième colonne par 10.

4
Lri

A dû faire un compte en voyant «awk» et «impossible» dans une phrase. Voici une solution awk-only sans créer de fichier temporaire:

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

Essayez d'inclure l'instruction dans votre fichier awk afin de pouvoir trouver la sortie dans un nouveau fichier. Ici le total est une valeur calculée.

print $total, total >> "new_file" 
0
debi