Utiliser sed et grep pour rechercher et remplacer

j'utilise egrep -R suivi d'une expression régulière contenant environ 10 syndicats, ainsi comme: .jpg | .png | .gif etc. Cela fonctionne bien, maintenant je voudrais remplacer toutes les cordes trouvées par .bmp

je pensais à quelque chose comme

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

donc la question ici est de savoir comment je fais une expression régulière syndicale similaire dans sed et comment je lui dis de sauvegarder les modifications dans le fichier à partir duquel il a obtenu les entrées.

92
demandé sur A-B-B 2009-07-23 10:19:27

6 réponses

utilisez cette commande:

egrep -lRZ "\.jpg|\.png|\.gif" . \
    | xargs -0 -l sed -i -e 's/\.jpg\|\.gif\|\.png/.bmp/g'
  • egrep : trouver des lignes de correspondance en utilisant des expressions régulières étendues

    • -l : seule liste correspondant aux noms de fichiers

    • -R : rechercher récursivement dans tous les répertoires donnés

    • -Z : utilisation "151950920" comme séparateur d'enregistrement

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

    • . : commencez la recherche dans le répertoire courant

  • xargs : exécuter une commande avec l'argument stdin

    • -0 : utiliser "151950920" comme séparateur d'enregistrement. Ceci est important pour correspondre au -Z de egrep et pour éviter d'être dupé par les espaces et les nouvelles lignes dans les noms de fichiers d'entrée.

    • -l : utilisez une ligne par commande comme paramètre

  • sed : le s tream ed itor

    • -i : remplacer le fichier d'entrée par la sortie sans faire une sauvegarde

    • -e : utilisez l'argument suivant comme expression

    • 's/\.jpg\|\.gif\|\.png/.bmp/g' : remplacer toutes les occurrences des cordes ".jpg" , ".gif" ou ".png" par ".bmp"

176
répondu David Schmitt 2014-03-16 00:34:13

honnêtement, bien que j'aime sed pour les tâches appropriées, c'est certainement une tâche pour perl -- c'est vraiment plus puissant pour ce genre de monocouches, surtout pour "l'écrire à l'endroit d'où il vient" (le commutateur -i de perl le fait pour vous, et vous permet aussi optionnellement de garder l'ancienne version autour par exemple avec un .bak ajouté, il suffit d'utiliser -i.bak à la place).

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

plutôt que des travaux compliqués dans sed (si même possible là) ou awk...

11
répondu Alex Martelli 2009-07-23 06:28:58

une autre façon de le faire

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 dans l'annuaire courant indiqué par .

-name le nom du fichier dans mon cas, ses pom.xml peut donner des jokers.

-exec exécuter

sed éditeur de flux

-i ignorer affaire 1519100920"

s pour remplacer

/4.6.0.../ chaîne de caractères à rechercher

/5.0.0.../ chaîne à remplacer

9
répondu Cyril Cherian 2013-05-22 13:07:56

Je ne pouvais pas faire fonctionner aucune des commandes sur cette page pour moi: le solution sed a ajouté une nouvelle ligne à la fin de tous les fichiers qu'il a traités, et le solution perl n'a pas été en mesure d'accepter assez d'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 va revenir dans l'arborescence courante du répertoire et remplacer search_regex par replacement_string dans tous les fichiers se terminant par .h ou .m .

j'ai également utilisé rpl à cette fin dans le passé.

5
répondu titaniumdecoy 2017-05-23 10:31:31

essayez quelque chose à l'aide d'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 ça devrait.

0
répondu Don Johe 2009-07-23 06:36:52

mon étui était je voulais remplacer foo:/Drive_Letter avec foo:/bar/baz/xyz Dans mon cas, j'ai pu le faire avec le code suivant. J'étais dans le même répertoire où il y avait beaucoup de fichiers.

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

espère que cela a aidé.

mise à jour s/foo:|Drive_letter:/foo:/ba/baz|xyz / g

0
répondu neo7 2013-09-12 20:23:33