Comment rechercher et remplacer plusieurs aiguilles par un seul mot via une seule expression?

8

Supposons que vous ayez un fichier texte:

foo fnord bar
bizz foo poit

Et maintenant, je voudrais remplacer "foo" et "bar" par "narf".

Je sais que je pourrais utiliser:

 sed -e 's/foo/narf/g' -e 's/bar/narf/g' fileName

Pourtant, je voudrais travailler avec un opérateur OR qui dit au regex de faire correspondre les deux aiguilles via une seule expression.

Frapper quelques manuels, je suppose que le tuyau devrait répondre à mes besoins, mais j'ai essayé

sed -e 's/foo|bar/narf/g' -i fileName

et cela n'a pas fonctionné et ce n'est même pas une erreur.

Qu'est-ce que je fais mal ici?

k0pernikus
la source

Réponses:

10

Utilisez l' -roption pour la syntaxe regexp étendue:

sed -r -e 's/foo|bar/narf/g'

Sinon, échappez à la disjonction en \|:

sed -e 's/foo\|bar/narf/g'
Stéphane Gimenez
la source
6

Il existe de nombreuses variantes de la syntaxe des expressions régulières . Les tout premiers outils dans le monde Unix qui avaient des expressions régulières n'avaient pas toutes les capacités des expressions régulières, seulement des jeux de caractères ( […]et .), des répétitions ( *) et des ancres de ligne ( ^et $). Les expressions régulières de base n'ont que ces opérateurs. Sed est un outil à l'ancienne et utilise des expressions rationnelles de base.

De nombreuses implémentations sed ont des extensions pour une correspondance regexp complète. Parce que le personnage |se représente lui-même, vous devez utiliser \|pour l'alternance, et de même \(et \)pour le regroupement. Notez que la norme POSIX ne requiert pas la \|prise en charge dans les expressions régulières de base , et certains systèmes (par exemple OpenBSD ) ne l'ont pas.

Certaines versions de sed ont la possibilité de passer aux expressions régulières étendues , où elles (…)sont utilisées pour le regroupement et l' |alternance. Avec GNU sed (c'est-à-dire sous Linux ou Cygwin) ou Busybox , passez l' -roption. Sur FreeBSD ou OSX , passez l' -Eoption.

Si votre sed n'a pas d'alternance, vous pouvez appeler à la awkplace. Il est mandaté par POSIX , mais un peu détaillé pour cette tâche, et il ne prend pas en charge les références arrières.

awk '{gsub(/foo|bar/, "narf")}' <fileName.old >fileName.new

Soit dit en passant, seuls GNU et Busybox sed prennent en charge le remplacement de fichiers en place. Awk et les autres versions de sed ne le font pas. Voir Puis-je faire `couper 'changer un fichier en place?

Si vous avez Perl, il est souvent pratique d'une manière un-outil-tout-pour le traitement de texte one-liners. La plupart de ce qui est facile dans sed, awk et le reste n'est pas beaucoup plus difficile dans Perl, et vous pouvez vous en tirer en apprenant un seul outil (si complexe).

perl -i -pe 's/foo|bar/narf/g' fileName
Gilles 'SO- arrête d'être méchant'
la source
0

Vous pouvez utiliser Vim en mode Ex:

ex -sc '%s/\vPA|QU/RO/g|x' file
  1. % sélectionner toutes les lignes

  2. s remplacer

  3. \v allume la magie

  4. g remplacement global

  5. x sauver et fermer

Steven Penny
la source