GNU Grep peut-il sortir un groupe sélectionné?

48

Est-il possible d'utiliser GNU grep pour obtenir un groupe mis en correspondance à partir d'une expression?

Exemple:

echo "foo 'bar'" | grep -oE "'([^']+)'"

Ce qui produirait "'bar'". Mais je voudrais juste avoir "bar", sans avoir à l'envoyer par le biais de grep une fois de plus (c'est-à-dire obtenir le groupe correspondant). Est-ce possible?

Torandi
la source

Réponses:

50

Vous pouvez utiliser sedpour cela. Sur BSD sed:

echo "foo 'bar'" | sed -E "s/.*'([^']+)'.*/\\1/"

Ou, sans l' -Eoption:

sed "s/.*'\([^']\+\)'.*/\1/"

Cela ne fonctionne pas pour une entrée multiligne. Pour cela vous avez besoin de:

sed -n "s/.*'\([^']\+\)'.*/\1/p"
jtbandes
la source
1
Hm, ça se passe sur ma machine (Mac OS X). Après un examen plus approfondi, consultez la page de manuel: "Les options -E, -a et -i sont des extensions non standard de FreeBSD et peuvent ne pas être disponibles sur d'autres systèmes d'exploitation."
jtbandes
1
Il est similaire à grep's -E: "Interprète les expressions régulières comme des expressions régulières étendues (modernes) plutôt que des expressions régulières de base (BRE). La page de manuel re_format (7) décrit complètement les deux formats."
jtbandes
1
-r semble à cela pour moi.
Torandi
1
@jtbandes: Vous n'avez pas besoin des fonctionnalités étendues pour cette expression .. Il me faut simplement 3 caractères d'échappement pour pouvoir l' ( ) +utiliser \( \) \+: C'est en fait la même chose:sed "s/.*'\([^']\+\)'.*/\1/"
Peter.O,
2
Cela ne fonctionne pas pour une entrée multiligne. Pour cela, vous avez besoin de: sed -n "s/.*'\([^']\+\)'.*/\1/p"
phreakhead 10/10
28

Bien que grep ne puisse pas générer de groupe spécifique, vous pouvez utiliser des assertions lookahead et behind pour obtenir ce que votre après:

echo "foo 'bar'" | grep -Po "(?<=')[^']+(?=')"

Aldrik
la source
8
grep -Pn'est pas disponible sur toutes les plateformes. Mais si c'est le cas, utiliser lookahead / behind est un très bon moyen de résoudre le problème.
Sébastien
1
Grep est-il intelligent avec les assertions de regard perdu? Comment se comporte-t-il avec de longs regards? Intègre-t-il les viseurs dans une sorte d' arborescence de "suffixes" avec le reste de la regex?
Ross Rogers
4

Vous pouvez utiliser \Kpour réinitialiser et supprimer le texte de correspondance de la main gauche avec un préfixe qui n'est pas ajouté au texte de correspondance:

$ echo "foo 'bar'" | grep -oP "'\K[^']+(?=')"
bar

GNU grep uniquement.

Drewk
la source