web-dev-qa-db-fra.com

Quels caractères spéciaux faut-il échapper dans les expressions régulières?

J'en ai assez de toujours essayer de deviner, si je dois échapper à des caractères spéciaux tels que '()[]{}|' etc.

C'est différent avec, par exemple, Python, sed, grep, awk, Perl, renommer, Apache, trouver, etc. Existe-t-il un ensemble de règles indiquant à quel moment je devrais ou non échapper à des caractères spéciaux? Cela dépend-il du type d'expression rationnelle, comme PCRE, POSIX ou les expressions rationnelles étendues?

359
Igor Katson

Les personnages que vous devez et que vous ne devez pas échapper dépendent de la saveur de regex avec laquelle vous travaillez.

Pour PCRE et la plupart des autres versions dites compatibles Perl, échappez à ces classes de caractères externes:

.^$*+?()[{\|

et ces classes de caractères internes:

^-]\

Pour les expressions rationnelles étendues POSIX (ERE), échappez à ces classes de caractères externes (identiques à PCRE):

.^$*+?()[{\|

Échapper à d'autres caractères est une erreur avec POSIX ERE.

Dans les classes de caractères, la barre oblique inverse est un caractère littéral dans les expressions régulières POSIX. Vous ne pouvez pas l'utiliser pour échapper à rien. Vous devez utiliser "placement intelligent" si vous souhaitez inclure des métacaractères de classe de caractères en tant que littéraux. Placez le ^ n'importe où sauf au début, le] au début et le - au début ou à la fin de la classe de caractères pour les faire correspondre à la lettre, par exemple:

[]^-]

Dans les expressions rationnelles de base POS (BRE), il s’agit de métacaractères que vous devez échapper pour supprimer leur signification:

.^$*[\

Les parenthèses et les accolades délaissées dans les BRE leur confèrent la signification particulière que leurs versions non échappées ont dans les ERE. Certaines implémentations (par exemple, GNU) donnent également une signification spéciale à d’autres caractères lorsqu’ils sont échappés, tels que \? et +. Échapper à un caractère autre que. ^ $ * () {} Est normalement une erreur avec les BRE.

Dans les classes de caractères, les BRE suivent la même règle que les ERE.

Si tout cela vous fait tourner la tête, prenez une copie de RegexBuddy . Sous l'onglet Créer, cliquez sur Insérer un jeton, puis sur Littéral. RegexBuddy ajoutera des échappées si nécessaire.

338
Jan Goyvaerts

Saveurs RegEx modernes (PCRE)

Inclut C, C++, Delphi, EditPad, Java, JavaScript, Perl, PHP (preg), PostgreSQL, PowerGREP, PowerShell, Python, REALbasic, Studio réel, Ruby, TCL, VB.Net, VBScript, wxWidgets , Schéma XML, Xojo, XRegExp.
La compatibilité PCRE peut varier

N'importe où: . ^ $ * + - ? ( ) [ ] { } \ |


Saveurs RegEx héritées (BRE/ERE)

Comprend awk, ed, egrep, emacs, GNUlib, grep, PHP (ereg), MySQL, Oracle, R, sed.
La prise en charge de PCRE peut être activée dans les versions ultérieures ou à l'aide d'extensions.

ERE/awk/egrep/emacs

En dehors d'une classe de caractères: . ^ $ * + ? ( ) [ { } \ |
Dans une classe de caractères: ^ - [ ]

BRE/ed/grep/sed

En dehors d'une classe de caractères: . ^ $ * [ \
Dans une classe de caractères: ^ - [ ]
Pour les littéraux, n'échappez pas: + ? ( ) { } |
Pour le comportement regex standard, échappez à: \+ \? \( \) \{ \} \|


Remarques

  • En cas de doute sur un caractère spécifique, il peut être échappé comme \xFF
  • Les caractères alphanumériques ne peuvent pas être échappés avec une barre oblique inverse
  • Les symboles arbitraires peuvent être échappés avec une barre oblique inversée dans PCRE, mais pas BRE/ERE (ils ne doivent être échappés que si nécessaire). Pour PCRE, ] - ne nécessite que l'échappement dans une classe de caractères, mais je les ai conservés dans une liste unique pour des raisons de simplicité.
  • Les chaînes d'expression citées doivent également avoir les caractères de citation environnants échappés, et souvent avec des barres obliques inverses doublées (comme "(\")(/)(\\.)" contre /(")(\/)(\.)/ en JavaScript)
  • Outre les échappements, différentes implémentations de regex peuvent prendre en charge différents modificateurs, classes de caractères, ancres, quantificateurs et autres fonctionnalités. Pour plus de détails, consultez regular-expressions.info , ou utilisez regex101.com pour tester vos expressions en direct
56
Beejor

Malheureusement, il n'existe pas vraiment de jeu de codes d'échappement, car ils varient en fonction de la langue utilisée.

Cependant, le fait de conserver une page telle que Page des outils d’expression régulière ou ceci Feuille de calcul d’expression régulière peut vous aider considérablement à filtrer les éléments.

22
Dillie-O

POSIX reconnaît plusieurs variantes d'expressions régulières - expressions régulières de base (BRE) et expressions régulières étendues (ERE). Et même alors, il y a des bizarreries à cause des implémentations historiques des utilitaires standardisés par POSIX.

Il n'y a pas de règle simple pour savoir quand utiliser quelle notation, ni même quelle notation une commande donnée utilise.

Découvrez le livre maîtriser les expressions régulières de Jeff Friedl.

5
Jonathan Leffler

Malheureusement, la signification de choses comme (et \) est permutée entre les expressions rationnelles de style Emacs et la plupart des autres styles. Si vous essayez de les échapper, vous ferez peut-être le contraire de ce que vous voulez.

Donc, vous devez vraiment savoir quel style vous essayez de citer.

4
Darron

Parfois, une simple évasion n'est pas possible avec les personnages que vous avez listés. Par exemple, l’utilisation d’une barre oblique inverse pour échapper à un crochet ne fonctionne pas dans la partie gauche d’une chaîne de substitution dans sed, à savoir:

sed -e 's/foo\(bar/something_else/'

J'ai tendance à simplement utiliser une définition de classe de caractères simple à la place, de sorte que l'expression ci-dessus devient

sed -e 's/foo[(]bar/something_else/'

que je trouve fonctionne pour la plupart des implémentations regexp.

Les classes de caractères BTW sont de jolis composants d'expression rationnelle Vanilla et ont donc tendance à fonctionner dans la plupart des situations où vous avez besoin de caractères d'échappement dans les expressions rationnelles.

Edit: Après le commentaire ci-dessous, je pensais mentionner le fait que vous devez également prendre en compte la différence entre les automates à états finis et les états non finis. automates lorsqu’on examine le comportement de l’évaluation des expressions rationnelles.

Vous voudrez peut-être consulter le "livre brillant", à savoir Effective Perl ( lien asservi d'Amazon ), en particulier le chapitre sur les expressions régulières, pour vous faire une idée de la différence entre les types d'évaluation des moteurs d'expressions régulières.

Le monde entier n'est pas un PCRE!

Quoi qu'il en soit, les expressions rationnelles sont tellement maladroites comparées à SNOBOL ! Maintenant que était un cours de programmation intéressant! Avec celui sur Simula .

Ah les joies d'étudier à UNSW à la fin des années 70! (-:

4
Rob Wells

Vraiment, il n'y en a pas. il existe environ un demi-zillion de syntaxes de regex différentes; ils semblent descendre à Perl, EMACS/GNU et AT & T en général, mais je suis toujours surpris aussi.

4
Charlie Martin

Pour savoir quand et quoi échapper sans tentative, il est nécessaire de comprendre précisément la chaîne de contextes traversés. Vous allez spécifier la chaîne du côté le plus éloigné à sa destination finale, à savoir la mémoire gérée par le code d'analyse des expressions rationnelles.

Sachez comment la chaîne en mémoire est traitée: s'il peut s'agir d'une chaîne simple dans le code ou d'une chaîne entrée sur la ligne de commande, il peut s'agir d'une ligne de commande interactive ou d'une ligne de commande indiquée dans un fichier de script Shell, ou à l'intérieur d'une variable en mémoire mentionnée par le code, ou d'un argument (chaîne) faisant l'objet d'une évaluation ultérieure, ou d'une chaîne contenant du code généré dynamiquement avec une sorte d'encapsulation quelconque ...

Chacun de ces contextes a affecté des caractères avec des fonctionnalités spéciales.

Lorsque vous voulez transmettre le caractère littéralement sans utiliser sa fonction spéciale (locale par rapport au contexte), vous devez l'échapper pour le contexte suivant ... ce qui pourrait nécessiter d'autres caractères d'échappement qui pourraient également être nécessaires. échappé dans le (s) contexte (s) précédent (s). De plus, il peut y avoir des choses comme l'encodage de caractères (le plus insidieux est utf-8 car il ressemble à ASCII pour les caractères communs, mais il peut éventuellement être interprété même par le terminal en fonction de ses paramètres, de sorte qu'il pourrait se comporter différemment, puis l'attribut de codage HTML/XML, il est nécessaire de comprendre le processus avec exactitude.

Par exemple. Une expression rationnelle dans la ligne de commande commençant par Perl -npe doit être transférée à un ensemble d'appels système exec se connectant en tant que canal des descripteurs de fichiers; chacun de ces appels système exécute une liste de arguments séparés par des espaces (non insérés), et éventuellement tuyaux (|) et redirection (> N> N> & M), parenthèses, développement interactif de * et ?, $(()) ... (tout cela sont des caractères spéciaux utilisés par * sh qui peuvent sembler interférer avec le caractère de l'expression régulière dans le contexte suivant, mais ils sont évalués dans l'ordre: avant la ligne de commande. La ligne de commande est lue par un programme comme bash/sh/csh/tcsh/zsh, essentiellement entre guillemets ou guillemets simples, l’échappement est plus simple mais il n’est pas nécessaire de citer une chaîne dans la ligne de commande car la plupart du temps, l’espace doit être préfixé par une barre oblique inversée; Il n'est pas nécessaire de laisser disponible la fonctionnalité expand pour les caractères * et?, mais cette analyse est aussi différente du contexte citation. Ensuite, lorsque la ligne de commande est évaluée, l'expression rationnelle obtenue en mémoire (non écrite dans la ligne de commande) reçoit le même traitement que dans un fichier source. Pour l'expression rationnelle, il y a un contexte de jeu de caractères entre crochets [], une expression régulière Perl peut être citée par un grand ensemble de caractères non alphanumériques (par exemple, m // ou m:/meilleur/pour/chemin: ...).

Vous avez plus de détails sur les caractères dans une autre réponse, qui sont très spécifiques au contexte final de l'expression rationnelle. Comme je l'ai indiqué, vous avez mentionné que vous trouviez l'échappement de l'expression rationnelle avec les tentatives, probablement parce qu'un contexte différent a un ensemble de caractères différent qui confond la mémoire des tentatives ).

2
Marco Munari

Pour PHP, "il est toujours prudent de faire précéder un non alphanumérique d'un"\"pour spécifier qu'il se représente tout seul." - http://php.net/manual/en/regexp.reference.escape.php .

Sauf si c'est un "ou".: /

Pour échapper aux variables de modèle regex (ou variables partielles) dans PHP, utilisez preg_quote ()

2
zylstra

https://perldoc.Perl.org/perlre.html#Quoting-metacharacters et https://perldoc.Perl.org/functions/quotemeta.html

Dans la documentation officielle, ces caractères sont appelés métacaractères. Exemple de citation:

my $regex = quotemeta($string)
s/$regex/something/
0
MUY Belgium