80 votes

Ligne de commande de Linux mondial de recherche et de remplacement

Je suis en train de rechercher et remplacer une chaîne de caractères dans tous les fichiers appariés par un grep sur une machine linux. J'ai quelques morceaux de ce que je veux faire, mais je ne suis pas sûr de la meilleure façon de chaîne tous ensemble.

grep -n 'foo' * me donnera de sortie sous la forme:

[filename]:[line number]:[text]

Pour chaque fichier renvoyé par la commande grep, j'aimerais remplacer "foo" par "bar" et écrire le résultat dans le fichier. Est-il une bonne façon de le faire? Peut-être une fantaisie de pipeline?

108voto

MattJ Points 5958

Cela semble être ce que vous voulez, basé sur l'exemple que vous avez donné:

sed -i 's/foo/bar/g' *

Il n'est pas récursive (il ne sera pas descendre dans les sous-répertoires). Pour une belle solution de remplacement dans les fichiers sélectionnés tout au long d'un arbre, je l'utiliserais trouver:

find -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;

L' *.html est l'expression que les fichiers doivent correspondre, l' .bak après l' -je fait une copie du fichier d'origine, avec une .bak extension (il peut être n'importe quelle extension) et le g à la fin de la sed expression indique à sed pour remplacer les multiples copies sur une seule ligne (plutôt que seulement le premier). L' -impression de trouver est une commodité pour afficher les fichiers qui ont été assortie. Tout cela dépend des versions exactes de ces outils sur votre système.

71voto

armandino Points 4360

Voulez-vous dire rechercher et remplacer une chaîne de caractères dans tous les fichiers appariés par grep?

perl -p -i -e 's/oldstring/newstring/g' `grep -ril searchpattern *`

Modifier

Depuis ce qui semble être un assez populaire de question que je pensais que je serais mise à jour.

Aujourd'hui, j'utilise surtout ack-grep que c'est plus convivial. Si la commande ci-dessus serait:

perl -p -i -e 's/old/new/g' `ack -l searchpattern`

Pour gérer les espaces dans les noms de fichiers, vous pouvez exécuter:

ack --print0 -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g'

vous pouvez en faire plus avec ack-grep. Dites que vous voulez restreindre la recherche aux fichiers HTML uniquement:

ack --print0 --html -l searchpattern | xargs -0 perl -p -i -e 's/old/new/g'

Et si le blanc de l'espace n'est pas un problème, c'est encore plus court:

perl -p -i -e 's/old/new/g' `ack -l --html searchpattern`
perl -p -i -e 's/old/new/g' `ack -f --html` # will match all html files

14voto

Keltia Points 8104

Si votre sed(1) a -i option, puis l'utiliser comme ceci:

for i in *; do
  sed -i 's/foo/bar/' $i
done

Si non, il y a plusieurs façons de variations sur la suivante en fonction de la langue dans laquelle vous souhaitez jouer:

ruby -i.bak -pe 'sub(%r{foo}, 'bar')' *
perl -pi.bak -e 's/foo/bar/' *

6voto

hans Points 31

J'aime et utilisé la solution ci-dessus ou de l'ensemble du système de recherche et de remplacement parmi des milliers de fichiers:

find -name '*.htm?' -print -exec sed -i.bak 's/foo/bar/g' {} \;

Je suppose avec le '*.htm?' au lieu de .html, il cherche et trouve .htm et .fichiers html comme.

- Je remplacer la .bak avec le système plus large utilisé tilde (~) pour faire le nettoyage des fichiers de sauvegarde plus facile.

3voto

koolb Points 31

find . -type f -print0 | xargs -0 <sed/perl/ruby cmd> va traiter plusieurs espace contenait les noms de fichiers à la fois le chargement d'un interprète par lot. Beaucoup plus rapide.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X