Regex correct ne fonctionne pas dans grep

13

J'ai ce regex:

(?<=prefix).*$

qui retourne tout caractère suivant la chaîne "préfixe" et cela fonctionne très bien sur tous les moteurs regex en ligne (par exemple https://regex101.com ). Le problème est lorsque j'utilise cette expression régulière dans bash:

grep '(?<=prefix).*$' <<< prefixSTRING

cela ne correspond à rien. Pourquoi cette expression régulière ne fonctionne pas avec grep?

mark009
la source
11
Cela montre vraiment pourquoi regex101 a besoin d'un sélecteur de saveur POSIX comme il le fait pour JS, Perl / PHP et Python. Je ne peux pas compter le nombre de fois que j'ai souhaité ça.
Jared Smith
En outre, le .*$correspond à n'importe quelle chaîne jusqu'à la fin de la ligne (ou à la fin de la chaîne), pas seulement n'importe quel caractère.
ilkkachu

Réponses:

38

Vous semblez avoir défini l'expression rationnelle correcte, mais vous n'avez pas défini les indicateurs suffisants en ligne de commande pour greple comprendre. Parce que par défaut grepprend en charge BRE et avec -Eindicateur, il fait ERE. Ce que vous avez (perspectives) n'est disponible que dans la version regex PCRE qui n'est prise en charge que dans GNU grepavec son -Pindicateur.

En supposant que vous devez extraire uniquement la chaîne correspondante après avoir prefixbesoin d'ajouter un indicateur supplémentaire -opour indiquer grepque n'imprime que la partie correspondante comme

grep -oP '(?<=prefix).*$' <<< prefixSTRING

Il existe également une version grepqui prend en charge les bibliothèques PCRE par défaut - pcregrepdans laquelle vous pouvez simplement faire

pcregrep -o '(?<=prefix).*$' <<< prefixSTRING

Des explications détaillées sur les différentes saveurs d'expression régulière sont expliquées dans cette merveilleuse réponse de Giles et les outils qui les implémentent

Inian
la source
38

Les expressions régulières sont disponibles dans de nombreuses saveurs différentes. Ce que vous montrez est une expression régulière de type Perl (PCRE, "Perl Compatible Regular Expression").

grepfait des expressions régulières POSIX. Ce sont des expressions régulières de base (BRE) et des expressions régulières étendues (ERE, si grepest utilisé avec l' -Eoption). Consultez le manuel de re_formatou regextout autre manuel similaire auquel votre grepmanuel se réfère sur votre système, ou les textes standard POSIX auxquels je viens de faire un lien.

Si vous utilisez GNU grep, vous seriez en mesure d'utiliser des expressions régulières de type Perl si vous grepl' greputilisiez avec l' -Poption spécifique à GNU .

Notez également que greprenvoie les lignes par défaut, pas les sous-chaînes de lignes. Encore une fois, avec GNU grep(et certaines autres grepimplémentations), vous pouvez utiliser l' -ooption pour obtenir uniquement le ou les bits qui correspondent à l'expression donnée de chaque ligne.

Notez que les deux -Pet -osont des extensions non standard de la spécification POSIX degrep .

Si vous n'utilisez pas GNU grep, vous pouvez utiliser à la sedplace pour obtenir le bit entre la chaîne prefixet la fin de la ligne:

sed -n 's/.*prefix\(.*\)/\1/p' file

Ce que cela fait est d'imprimer uniquement les lignes qui sedparviennent à appliquer la substitution donnée. La substitution remplacera la ligne entière qui correspond à l'expression (qui est un BRE), avec le morceau qui se produit après la chaîne prefix.

Notez que s'il y a plusieurs instances de prefixsur une ligne, la sedvariation retournerait la chaîne après la dernière , tandis que la grepvariation GNU retournerait la chaîne après la première (qui inclurait les autres instances de prefix).

La sedsolution serait portable sur tous les systèmes de type Unix.

Kusalananda
la source
6

Comme les autres réponses l'ont indiqué, grepn'utilise pas d'arôme regex avec lookbehinds (par défaut avec GNU grep, ou pas du tout avec d'autres versions).

Si vous vous trouvez incapable d'utiliser GNU grepou pcregrep, vous pouvez l'utiliser perlsi vous l'avez.

La ligne de commande équivalente à perlserait:

perl -ne 'print if /(?<=prefix).*$/' <<< prefixSTRING

Vous placez l'expression régulière souhaitée entre les barres obliques. Lorsque vous utilisez Perl, cela utilise la saveur regex de Perl .

quantum
la source
ou print "$&\n" if ...s'ils veulent sortir uniquement la partie après leprefix
ilkkachu