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
.
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.
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
.
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).
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.
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
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"