Est-il possible d'utiliser gawk
l' -i inplace
option de et d'imprimer également des choses sur stdout
?
Par exemple, si je voulais mettre à jour un fichier et s'il y a des changements, imprimez le nom du fichier et les lignes modifiées pour que stderr
je puisse faire quelque chose comme
find -type f -name 'myfiles' -exec gawk -i inplace '{if(gsub(/pat/, "repl")) { print FILENAME > "/proc/self/fd/2" ; print > "/proc/self/fd/2"; } print;}' {} +
mais existe-t-il un moyen d'utiliser à la stdout
place, ou un moyen plus propre d'imprimer ce bloc sur le flux alternatif?
find -type f -name 'myfiles' -exec grep -q 'pattern' {} \; -print -exec gawk -i inplace '{do_your_sub_and_print_to_dev/stderr_too}' {} \;
ça, vous n'utiliserez awk que pour modifier les fichiers qui contiennent réellement des lignes correspondant à ce modèle.grep
peut être. Mon premier réflexe est d'éviter de devoir "traiter" deux fois le fichier, mais je ne serais pas du tout surpris s'il est en effet plus rapide néanmoins. Cela montre simplement pourquoi je peux faire confiance à mon instinct pour les tâches de profilage-print -exec gawk
n'est plus exécutée) et 2) il s'arrêtera au 1er match, donc à moins que le 1er match ne soit sur le dernière ligne, vous ne traitez toujours pas le fichier entier deux fois (c'est plus comme 1.X fois). De plus, si celagawk -i inplace
fonctionne,sed -i
le fichier sera modifié sur place de toute façon - c'est-à-dire la mise à jour des horodatages, de l'inode, etc. même s'il n'y avait rien à modifier ...Réponses:
Vous devez utiliser
/dev/stderr
ou/dev/fd/2
au lieu de/proc/self/fd/2
.gawk
gère/dev/fd/x
et/dev/stderr
par lui-même (que le système possède ou non ces fichiers).Quand vous faites:
gawk
fait unwrite(2, "x\n")
, tandis que lorsque vous faites:comme il ne traite pas
/proc/self/fd/x
spécialement, il fait:Le premier
/proc/self/fd
est spécifique à Linux et sur Linux, il est problématique. Les deux versions ci-dessus ne sont pas équivalentes lorsque stderr est vers un fichier normal ou autre recherchable ou vers un socket (pour lequel ce dernier échouerait) (sans oublier qu'il gaspille un descripteur de fichier).Cela étant dit, si vous devez écrire sur la sortie standard, vous devez l'enregistrer dans un autre fd comme:
gawk
redirige stdout avec in-place vers le fichier. C'est nécessaire parce que, par exemple, vous voudriez:pour stocker la
uname
sortie dans lefile
.la source
Juste pour le plaisir, une autre approche utilisant uniquement des caractéristiques POSIX
find
,sh
,grep
et (notamment)ex
:(Tous les sauts de ligne dans la commande ci-dessus sont facultatifs; il peut être condensé en une seule ligne.)
Ou, sans doute plus lisible:
:)
(Cette commande n'est pas testée; les modifications sont les bienvenues si je fais des gaffes.)
la source