Disons que j'ai un fichier :
# file: 'test.txt'
foobar bash 1
bash
foobar happy
foobar
Je veux seulement savoir quels mots apparaissent après "foobar" ;, donc je peux utiliser cette regex :
"foobar \(\w\+\)"
Les parenthèses indiquent que je m'intéresse particulièrement au mot juste après foobar. Mais quand je fais un grep "foobar \(\w\+\)" ; test.txt
, j'obtiens les lignes entières qui correspondent à la regex entière, plutôt que juste "le mot après foobar" :
foobar bash 1
foobar happy
Je préférerais de loin que le résultat de cette commande ressemble à ceci :
bash
happy
Existe-t-il un moyen d'indiquer à grep de n'afficher que les éléments qui correspondent au groupe (ou à un groupe spécifique) d'une expression régulière ?
GNU grep possède l'option -P
pour les regex de style perl, et l'option -o
pour n'afficher que ce qui correspond au motif. Ces options peuvent être combinées en utilisant des assertions de contournement (décrites dans [Extended Patterns in the perlre manpage][1]) pour enlever une partie du motif grep de ce qui est déterminé comme ayant correspondu pour les besoins de -o
.
$ grep -oP 'foobar \K\w+' test.txt
bash
happy
$
Le K
est la forme courte (et plus efficace) de (?<=motif)`` que vous utilisez comme une assertion look-behind de largeur zéro devant le texte que vous voulez afficher.
(?=modèle)` peut être utilisé comme une assertion look-ahead de largeur zéro après le texte que vous voulez éditer.
Par exemple, si vous voulez faire correspondre le mot entre foo
et bar
, vous pouvez utiliser :
$ grep -oP 'foo \K\w+(?= bar)' test.txt
ou (par symétrie)
$ grep -oP '(?<=foo )\w+(?= bar)' test.txt
Le grep standard ne peut pas le faire, mais [les versions récentes de GNU grep le peuvent] (https://unix.stackexchange.com/questions/13466/can-grep-output-only-specified-groupings-that-match/13472#13472). Vous pouvez vous tourner vers sed, awk ou perl. Voici quelques exemples qui font ce que vous voulez sur votre exemple d'entrée ; ils se comportent légèrement différemment dans les cas particuliers.
Remplacer foobar word other stuff
par word
, imprimer seulement si un remplacement est effectué.
sed -n -e 's/^foobar \([[:alnum:]]\+\).*/\1/p'
Si le premier mot est foobar
, affiche le deuxième mot.
awk '$1 == "foobar" {print $2}'
Supprimez foobar
si c’est le premier mot, et sautez la ligne sinon ; puis supprimez tout ce qui suit le premier espace et imprimez.
perl -lne 's/^foobar\s+// or next; s/\s.*//; print'