Tester la recherche récursive sed et remplacer avant d'exécuter

13

Existe-t-il un moyen d'exécuter une recherche récursive d'essai et de remplacer using sed, avant de l'exécuter réellement? Je veux juste imprimer les résultats avant de faire la recherche et le remplacement. Quelque chose comme faire écho aux résultats de,

grep -rl term1 . |xargs sed -i -e 's/term1/term2/'
user251482
la source
Faites une copie des données, exécutez votre commande, inspectez le résultat.
Kusalananda

Réponses:

10

Vous pouvez exécuter sedsans -iet parcourir la sortie avecless

grep -rl --null term1 . | xargs -0 sed -e 's/term1/term2/' | less

Ensuite, exécutez sedavec -i.bakpour créer des sauvegardes que vous pourrez ensuite différencier

grep -rl --null term1 . | xargs -0 sed -i.bak -e 's/term1/term2/'
diff somefile.bak somefile
# verify changes were correct

Modifier: comme suggéré dans le commentaire, utilisez grep --null | xargs -0. Cela provoque la fin des noms de fichiers par l'octet nul, ce qui le rend sûr pour les noms de fichiers avec des caractères inhabituels comme la nouvelle ligne. Oui, \nest un caractère valide dans un nom de fichier Unix. Les seuls caractères interdits sont le slash /et le caractère nul\0

grebneke
la source
Intéressant, j'ai essayé de trouver le sens de -i mais il n'était pas répertorié sous man sed. Votre solution a fonctionné. Quelle serait la meilleure façon selon vous de simplement lister les lignes, pas le fichier entier? Au lieu de siffler en moins j'ai sifflé | grep term2, qui fonctionnait en quelque sorte, mais j'ai également obtenu une sortie avec des caractères étranges.
user251482
@ user251482 - "Il suffit de lister les lignes", comme dans "afficher un diff entre l'ancien et le nouveau fichier"?
grebneke
1
@StephaneChazelas Oui, ou mieux encore grep -rl --nullcar OP ne spécifiait pas OS, et -Zsignifie quelque chose de différent sur BSD / OSX (décompresser). --nullest le même sur GNU et BSD
grebneke
1
@grebneke. Bon point, mais notez que l'OP utilise la syntaxe GNU sed, donc nous pouvons supposer qu'il n'est pas sur BSD. Notez que grepc'est (un fork de) le grep GNU sur FreeBSD et NetBSD. Sur NetBSD, -Zsignifie toujours --null(selon la page de manuel), mais je suis d'accord - null est plus portable. A noter également que ni - nul ni -Z ne travaille sur OpenBSD
Stéphane Chazelas
1
@grebneke, c'est sed -i '' -e s/.../en BSD sed(pas d'options optionnelles là-bas)
Stéphane Chazelas
5

Utiliser sedavec findau lieu degrep

Tout d'abord, j'emploierais findplutôt que grep, et ce pour trois bonnes raisons:

  1. findpermet une sélection plus précise des fichiers. Par exemple, grep -r string *.txtne produira des fichiers que dans le répertoire courant; pas ceux des sous-répertoires.
  2. findest livré avec la puissante -execoption qui élimine le besoin de la --null … |xargs 0construction entière .
  3. Les options -readableet -writablede findpermettront d'éviter de perdre du temps sur des fichiers inaccessibles.

Test de capture

Cela dit, grepcela se prête à un premier test pour voir ce qui serait capturé:

$ find . -exec grep term1 {} \;

ou plus précisément:

$ find . -type f -name '*.txt' -readable -writable -exec grep term1 {} \;

Marche à sec

Maintenant, procédez à un sedessai à sec. L' sedoption -nest synonyme de --quietet tout pà la fin de l' sedexpression imprimera l'espace de motif actuel.

$ find . -exec sed -n 's/term1/term2/gp' {} \;

ou plus précisément:

$ find . -type f -name '*.txt' -readable -writable -exec sed -n 's/term1/term2/gp' {} \;

Exécution

Si tout semble correct, lancez la commande définitive en remplaçant l' sedoption -npar -ipour "en place" et en supprimant le pà la fin.

$ find . -exec sed -i 's/term1/term2/g' {} \;

ou plus précisément:

$ find . -type f -name '*.txt' -readable -writable -exec sed -i 's/term1/term2/g' {} \;

Plus d' findexemples

Plus d' findexemples peuvent être trouvés ici .

Serge Stroobandt
la source