J'ai écrit une expression régulière qui fonctionne bien dans un certain programme (grep, sed, awk, perl, python, ruby, ksh, bash, zsh, find, emacs, vi, vim, gedit, …). Mais lorsque je l'utilise dans un programme différent (ou sur une variante Unix différente), il cesse de correspondre. Pourquoi ?
Réponse acceptée :
Malheureusement, pour des raisons historiques, différents outils ont une syntaxe d'expression régulière légèrement différente, et parfois certaines implémentations ont des extensions qui ne sont pas prises en charge par d'autres outils. Bien qu'il existe un terrain d'entente, il semble que chaque créateur d'outils ait fait des choix différents.
La conséquence est que si vous avez une expression régulière qui fonctionne dans un outil, vous devrez peut-être la modifier pour qu'elle fonctionne dans un autre outil. Les principales différences entre les outils courants sont :
- si les opérateurs
+?|(){}
exiger une barre oblique inverse ; - quelles extensions sont prises en charge au-delà des bases
.[]*^$
et généralement+?|()
Dans cette réponse, je liste les principales normes. Consultez la documentation des outils que vous utilisez pour plus de détails.
La comparaison de Wikipédia des moteurs d'expressions régulières contient un tableau répertoriant les fonctionnalités prises en charge par les implémentations courantes.
Expressions régulières de base (BRE)
Les expressions régulières de base sont codifiées par le standard POSIX. C'est la syntaxe utilisée par grep
, sed
et vi
. Cette syntaxe offre les fonctionnalités suivantes :
^
et$
correspond uniquement au début et à la fin d'une ligne..
correspond à n'importe quel caractère (ou n'importe quel caractère sauf une nouvelle ligne).[…]
correspond à n'importe quel caractère indiqué entre parenthèses (jeu de caractères). Si le premier caractère après la parenthèse ouvrante est un^
, les caractères qui ne sont pas répertoriés sont mis en correspondance à la place. Pour inclure un]
, placez-le immédiatement après l'ouverture[
(ou après[^
s'il s'agit d'un ensemble négatif). Si-
est entre deux caractères, il dénote une plage ; pour inclure un-
littéral , placez-le là où il ne peut pas être analysé en tant que plage.- Barre oblique inverse avant l'un des
^$.*[
cite le caractère suivant. *
correspond au caractère ou à la sous-expression qui précède 0, 1 ou plusieurs fois.(…)
est un groupe syntaxique, à utiliser avec le*
opérateur ou backreferences etDIGIT
remplacements.- Références
1
,2
, … correspondent au texte exact correspondant au groupe correspondant, par ex.(fo*)(ba*)1
correspond àfoobaafoo
mais pasfoobaafo
. Il n'y a pas de moyen standard de se référer au 10ème groupe et au-delà (la signification standard de10
est le premier groupe suivi d'un).
Les fonctionnalités suivantes sont également standard, mais absentes de certaines implémentations restreintes :
{m,n}
correspond au caractère ou à la sous-expression précédente entre m à n fois; n ou m peut être omis, et{m}
signifie exactement m .- À l'intérieur des crochets, des classes de caractères peuvent être utilisées, par exemple
[[:alpha:]]
correspond à n'importe quelle lettre. Les implémentations modernes des expressions entre parenthèses) incluent également des éléments de classement comme[.ll.]
et des classes d'équivalence comme[=a=]
.
Les extensions suivantes sont courantes (en particulier dans les outils GNU), mais elles ne se trouvent pas dans toutes les implémentations. Consultez le manuel de l'outil que vous utilisez.
|
pour l'alternance :foo|bar
correspond àfoo
oubar
.?
(abréviation de{0,1}
) et+
(abréviation de{1,}
) correspondent au caractère ou à la sous-expression qui précède au plus 1 fois, ou au moins 1 fois respectivement.n
correspond à une nouvelle ligne,t
correspond à un onglet, etc.w
correspond à n'importe quel mot constitutif (abréviation de[_[:alnum:]]
mais avec des variations en termes de localisation) etW
correspond à tout caractère qui n'est pas un constituant de mot.<
et>
faire correspondre la chaîne vide uniquement au début ou à la fin d'un mot respectivement ;b
correspond à l'un ou l'autre, etB
correspond à oùb
pas.
Notez que les outils sans le |
L'opérateur n'a pas toute la puissance des expressions régulières. Les références arrière permettent quelques choses supplémentaires qui ne peuvent pas être faites avec des expressions régulières au sens mathématique.
Expressions régulières étendues (ERE)
Les expressions régulières étendues sont codifiées par le standard POSIX. Leur avantage majeur par rapport à BRE est la régularité :tous les opérateurs standards sont des caractères de ponctuation nus, une barre oblique inverse devant un caractère de ponctuation le cite toujours. C'est la syntaxe utilisée par awk
, grep -E
ou egrep
, GNU sed -r
, et le =~
de bash opérateur. Cette syntaxe offre les fonctionnalités suivantes :
^
et$
correspond uniquement au début et à la fin d'une ligne..
correspond à n'importe quel caractère (ou n'importe quel caractère sauf une nouvelle ligne).[…]
correspond à n'importe quel caractère indiqué entre parenthèses (jeu de caractères). Complémentation avec un^
initial et les gammes fonctionnent comme dans BRE (voir ci-dessus). Les classes de caractères peuvent être utilisées mais sont absentes de quelques implémentations. Les implémentations modernes prennent également en charge les classes d'équivalence et les éléments de classement. Une barre oblique inverse entre parenthèses cite le caractère suivant dans certaines implémentations mais pas toutes ; utilisez\
signifie une barre oblique inverse pour la portabilité.(…)
est un groupe syntaxique, à utiliser avec*
ouDIGIT
remplacements.|
pour l'alternance :foo|bar
correspond àfoo
oubar
.*
,+
et?
correspond au caractère ou à la sous-expression qui précède un certain nombre de fois :0 ou plus pour*
, 1 ou plus pour+
, 0 ou 1 pour?
.- La barre oblique inverse cite le caractère suivant s'il n'est pas alphanumérique.
{m,n}
correspond au caractère ou à la sous-expression précédente entre m et n fois (absent de certaines implémentations); n ou m peut être omis, et{m}
signifie exactement m .- Quelques extensions courantes comme dans BRE :
DIGIT
backreferences (notamment absentes dans awk sauf dans l'implémentation de busybox où vous pouvez utiliser$0 ~ "(...)\1"
); caractères spéciauxn
,t
, etc.; limites de motsb
etB
, constituants du motb
etB
, …
PCRE (expressions régulières compatibles Perl)
PCRE sont des extensions d'ERE, introduites à l'origine par Perl et adoptées par GNU grep -P
et de nombreux outils et langages de programmation modernes , généralement via la bibliothèque PCRE. Voir la documentation Perl pour une mise en forme agréable avec des exemples. Toutes les fonctionnalités de la dernière version de Perl ne sont pas prises en charge par PCRE (par exemple, l'exécution de code Perl n'est prise en charge qu'en Perl). Voir le manuel PCRE pour un résumé des fonctionnalités prises en charge. Les principaux ajouts à ERE sont :
(?:…)
est un groupe non capturant :comme(…)
, mais ne compte pas pour les références arrière.(?=FOO)BAR
(anticipation) correspond àBAR
, mais seulement s'il existe également une correspondance pourFOO
commençant à la même position. Ceci est très utile pour ancrer une correspondance sans inclure le texte suivant dans la correspondance :foo(?=bar)
correspond àfoo
mais seulement s'il est suivi debar
.(?!FOO)BAR
(anticipation négative) correspond àBAR
, mais il n'y a pas non plus de correspondance pourFOO
au même poste. Par exemple(?!foo)[a-z]+
correspond à tout mot en minuscule qui ne commence pas parfoo
;[a-z]+(?![0-9)
correspond à tout mot en minuscule qui n'est pas suivi d'un chiffre (donc dansfoo123
, il correspond àfo
mais pasfoo
).(?<=FOO)BAR
(lookbehind) correspond àBAR
, mais seulement s'il est immédiatement précédé d'une correspondance pourFOO
.FOO
doit avoir une longueur connue (vous ne pouvez pas utiliser d'opérateurs de répétition tels que*
). Ceci est très utile pour ancrer une correspondance sans inclure le texte précédent dans la correspondance :(?<=^| )foo
correspond àfoo
mais seulement s'il est précédé d'un espace ou du début de la chaîne.(?<!FOO)BAR
(lookbehind négatif) correspond àBAR
, mais seulement s'il n'est pas immédiatement précédé d'une correspondance pourFOO
.FOO
doit avoir une longueur connue (vous ne pouvez pas utiliser d'opérateurs de répétition tels que*
). Ceci est très utile pour ancrer une correspondance sans inclure le texte précédent dans la correspondance :(?<![a-z])foo
correspond àfoo
mais seulement s'il n'est pas précédé d'une lettre minuscule.
Emacs
La syntaxe d'Emacs est intermédiaire entre BRE et ERE. En plus d'Emacs, c'est la syntaxe par défaut pour -regex
dans GNU trouver. Emacs propose les opérateurs suivants :
^
,$
,.
,[…]
,*
,+
,?
comme dans ERE(…)
,|
,{…}
,DIGIT
comme dans BRE- plus de séquences de lettres avec barre oblique inversée ;
<
et>
pour les limites de mots ; et plus encore dans les versions récentes d'Emacs, qui ne sont souvent pas prises en charge par d'autres moteurs avec une syntaxe de type Emacs.
globules Shell
Les shell globs (wildcards) effectuent une correspondance de modèle avec une syntaxe complètement différente des expressions régulières et moins puissante. En plus des shells, ces jokers sont disponibles avec d'autres outils tels que find -name
et les filtres rsync. Les modèles POSIX incluent les fonctionnalités suivantes :
?
correspond à n'importe quel caractère unique.[…]
est un jeu de caractères comme dans les syntaxes d'expressions régulières courantes. Certains shells ne prennent pas en charge les classes de caractères. Certains shells nécessitent!
au lieu de^
pour nier l'ensemble.*
correspond à n'importe quelle séquence de caractères (souvent sauf/
lors de la correspondance des chemins de fichiers ; si/
est exclu de*
, puis**
inclut parfois/
, mais consultez la documentation de l'outil).- La barre oblique inverse cite le caractère suivant.
Ksh offre des fonctionnalités supplémentaires qui donnent à son pattern matching toute la puissance des expressions régulières. Ces fonctionnalités sont également disponibles dans bash après avoir exécuté shopt -s extglob
. Zsh a une syntaxe différente mais peut également prendre en charge la syntaxe de ksh après setopt ksh_glob
.