web-dev-qa-db-fra.com

Utiliser sed et grep/egrep pour rechercher et remplacer

J'utilise egrep -R suivi d'une expression régulière contenant environ 10 unions, donc, comme: .jpg | .png | .gif etc. Cela fonctionne bien, maintenant j'aimerais remplacer toutes les chaînes trouvées par .bmp

Je pensais à quelque chose comme

egrep -lR "\.jpg|\.png|\.gif" . | sed "s/some_expression/.jpg/" file_it_came_form

le problème est donc de savoir comment créer une expression régulière d'union similaire dans sed et comment lui demander de sauvegarder les modifications apportées au fichier à partir duquel il a reçu les données.

93
Ori

Utilisez cette commande:

egrep -lRZ "\.jpg|\.png|\.gif" . \
    | xargs -0 -l sed -i -e 's/\.jpg\|\.gif\|\.png/.bmp/g'
  • egrep: recherche les lignes correspondantes à l'aide d'expressions régulières étendues

    • -l: liste uniquement les noms de fichiers correspondants

    • -R: recherche récursive dans tous les répertoires donnés

    • -Z: utilisez \0 comme séparateur d'enregistrement

    • "\.jpg|\.png|\.gif": correspond à l'une des chaînes ".jpg", ".gif" ou ".png"

    • .: lance la recherche dans le répertoire en cours

  • xargs: exécuter une commande avec stdin comme argument

    • -0: utilisez \0 comme séparateur d'enregistrement. Cela est important pour faire correspondre le -Z de egrep et éviter de se laisser berner par des espaces et des nouvelles lignes dans les noms de fichiers en entrée.

    • -l: utilise une ligne par commande en paramètre

  • sed: le s tream ed itor

    • -i: remplace le fichier d'entrée par la sortie sans effectuer de sauvegarde

    • -e: utilise l'argument suivant comme expression

    • 's/\.jpg\|\.gif\|\.png/.bmp/g': remplace toutes les occurrences des chaînes ".jpg", ".gif" ou ".png" par ".bmp"

178
David Schmitt

Honnêtement, bien que j'aime sed pour les tâches appropriées, ceci est certainement une tâche pour Perl. Il est vraiment plus puissant pour ce type de ligne unique, en particulier pour "le restituer à l'endroit d'où il provient" (le commutateur -i de Perl le fait pour vous, et vous permet éventuellement de conserver l'ancienne version, par exemple avec un .bak ajouté, utilisez plutôt -i.bak à la place).

Perl -i.bak -pe 's/\.jpg|\.png|\.gif/.jpg/

plutôt que de travailler dans sed (si possible) ou awk ...

11
Alex Martelli

Une autre façon de faire ça 

find . -name *.xml -exec sed -i "s/4.6.0-SNAPSHOT/5.0.0-SNAPSHOT/" {} \;

Un peu d'aide concernant la commande ci-dessus

La recherche fera la recherche pour vous sur le répertoire courant indiqué par .

-name le nom du fichier dans mon cas, son pom.xml peut donner des caractères génériques.

-exec execute

sed éditeur de flux

-i ignorer la casse

s est pour substitut

/4.6.0.../ Chaîne à rechercher

/5.0.0.../ Chaîne à remplacer

9
Cyril Cherian

Aucune des commandes de cette page ne fonctionnait pour moi: la solution sed a ajouté une nouvelle ligne à la fin de tous les fichiers qu'elle traitait et la solution Perl était incapable d'en accepter suffisamment. arguments de find. J'ai trouvé cette solution qui fonctionne parfaitement:

find . -type f -name '*.[hm]' -print0 
    | xargs -0 Perl -pi -e 's/search_regex/replacement_string/g'

Cela permettra de rétablir l’arborescence actuelle et de remplacer search_regex par replacement_string dans tous les fichiers se terminant par .h ou .m.

J'ai aussi utilisé rpl à cette fin dans le passé.

5
titaniumdecoy

Mon cas d'utilisation était que je voulais remplacer foo:/Drive_Letter par foo:/bar/baz/xyzEn ce qui me concerne, j'ai pu le faire avec le code suivant .

find . -name "*.library" -print0 | xargs -0 sed -i '' -e 's/foo:\/Drive_Letter:/foo:\/bar\/baz\/xyz/g'

espérons que cela a aidé.

MISE À JOUR S | foo:/Drive_letter: | foo:/ba/baz/xyz | g 

0
neo7

essayez quelque chose en utilisant une boucle for

 for i in `egrep -lR "YOURSEARCH" .` ; do echo  $i; sed 's/f/k/' <$i >/tmp/`basename $i`; mv /tmp/`basename $i` $i; done

pas joli, mais devrait faire.

0
Don Johe