Dis 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", je peux donc utiliser cette regex:
"foobar \(\w\+\)"
Les parenthèses indiquent que j’ai un intérêt particulier pour le mot juste après foobar. Mais quand je fais un grep "foobar \(\w\+\)" test.txt
, je reçois 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 beaucoup que le résultat de cette commande ressemble à ceci:
bash
happy
Existe-t-il un moyen d'indiquer à grep de ne générer que les éléments correspondant au groupe (ou à un groupe spécifique) dans une expression régulière?
text-processing
grep
regular-expression
Cory Klein
la source
la source
perl -lne 'print $1 if /foobar (\w+)/' < test.txt
Réponses:
GNU grep a l’
-P
option pour les expressions rationnelles de style Perl et l’-o
option d’imprimer uniquement ce qui correspond au modèle. Ceux-ci peuvent être combinés à l'aide d'assertions de recherche (décrites dans la section relative aux modèles étendus de la page de manuel perlre ) pour supprimer une partie du modèle grep de ce qui a été déterminé comme ayant correspondu-o
.La
\K
est la forme abrégée (et la plus efficace)(?<=pattern)
que vous utilisez comme assertion de suivi de largeur nulle avant le texte que vous souhaitez afficher.(?=pattern)
peut être utilisé comme une affirmation d'anticipation de largeur zéro après le texte que vous souhaitez générer.Par exemple, si vous voulez faire correspondre le mot entre
foo
etbar
, vous pouvez utiliser:ou (pour symétrie)
la source
sed(1)
grep -oP 'foobar \K\w+' test.txt
rien ne sort avec les OPtest.txt
. La version de grep est 2.5.1. Quel pourrait être le problème? O_OGrep standard ne peut pas faire cela, mais les versions récentes de GNU grep le peuvent . Vous pouvez vous tourner vers sed, awk ou perl. Voici quelques exemples qui font ce que vous voulez dans votre exemple d’entrée. ils se comportent légèrement différemment dans les cas de coin.
Remplacer
foobar word other stuff
parword
, n'imprimez que si un remplacement est effectué.Si le premier mot est
foobar
, imprimez le deuxième mot.Effacez-le
foobar
si c'est le premier mot et sautez la ligne sinon; puis tout dépouiller après le premier espace et imprimer.la source
grep
. Mais la syntaxe de ces commandes semble très familière maintenant que je suis familiarisé avec les fonctions de recherche et remplacement de vim, ainsi que les expressions rationnelles. Merci beaucoup.grep
ne prend pas en charge PCRE.la source
^
et$
sont étrangers car.*
est un match gourmand. Cependant, les inclure pourrait aider à clarifier l'intention de la regex.Eh bien, si vous savez que foobar est toujours le premier mot ou la première ligne, vous pouvez utiliser couper. Ainsi:
la source
-o
commutateur sur grep est largement implémenté (plus que les extensions Gnu grep), donc celagrep -o "foobar" test.file | cut -d" " -f2
augmentera l'efficacité de cette solution, qui est plus portable que d'utiliser des assertions lookbehind.grep -o "foobar .*
"ougrep -o "foobar \w+"
.Si PCRE n'est pas pris en charge, vous pouvez obtenir le même résultat avec deux invocations de grep. Par exemple, pour saisir le mot après foobar, procédez comme suit :
Ceci peut être étendu à un mot arbitraire après foobar comme ceci (avec ERE pour la lisibilité):
Sortie:
Notez que l'index
i
est basé sur zéro.la source
pcregrep
a une-o
option plus intelligente qui vous permet de choisir les groupes de capture que vous voulez générer. Donc, en utilisant votre exemple de fichier,la source
L'utilisation
grep
n'est pas compatible entre plates-formes, car-P
/--perl-regexp
n'est disponible que sous GNUgrep
, pas sous BSDgrep
.Voici la solution utilisant
ripgrep
:Selon
man rg
:Connexes: GH-462 .
la source
J'ai trouvé la réponse de @jgshawkey très utile.
grep
sed n'est pas un bon outil pour cela, mais sed l'est, bien que nous ayons ici un exemple qui utilise grep pour saisir une ligne pertinente.La syntaxe regex de sed est idiosyncratique si vous n’êtes pas habitué.
Voici un autre exemple: celui-ci analyse la sortie de xinput pour obtenir un entier ID
et je veux 19
Notez la syntaxe de la classe:
et la nécessité d'échapper à ce qui suit
+
Je suppose qu'une seule ligne correspond.
la source
grep
, en supposant que 'TouchPad' est à gauche de 'id':echo "SynPS/2 Synaptics TouchPad id=19 [slave pointer (2)]" | sed -nE "s/.*TouchPad.+id=([0-9]+).*/\1/p"