web-dev-qa-db-fra.com

Liste de tous les caractères spéciaux à échapper dans une expression rationnelle

J'essaie de créer une application qui correspond à un modèle de message avec un message qu'un utilisateur tente d'envoyer. J'utilise regex Java pour faire correspondre le message. Le modèle/message peut contenir des caractères spéciaux.

Comment pourrais-je obtenir la liste complète des caractères spéciaux à échapper pour que mes expressions rationnelles fonctionnent et correspondent dans le maximum de cas possibles?

Existe-t-il une solution universelle pour échapper à tous les caractères spéciaux de Java regex?

83
Avinash Nair

Vous pouvez consulter le javadoc de la classe Pattern: http://docs.Oracle.com/javase/8/docs/api/Java/util/regex/Pattern.html

Si vous voulez le caractère normal et non le sens spécial, vous devez vous échapper de tout caractère indiqué ici.

Comme solution peut-être plus simple, vous pouvez mettre le modèle entre\Q et\E - tout ce qui les sépare est considéré comme échappé.

75
Sorin

Pour vous échapper, vous pouvez simplement utiliser ceci depuis Java 1.5 :

Pattern.quote("$test");

Vous ferez correspondre exactement le Word $test

20
madx

Sur la suggestion de @ Sorin concernant la documentation Java Pattern, il semble que les caractères à échapper sont au moins les suivants:

\.[{(*+?^$|
5
pete

Combinant ce que tout le monde a dit, je propose ce qui suit, afin que la liste des caractères spéciaux de RegExp soit clairement listée dans leur propre chaîne, et pour éviter de devoir analyser visuellement des milliers de "\\". Cela semble bien fonctionner pour moi:

final String regExSpecialChars = "<([{\\^-=$!|]})?*+.>";
final String regExSpecialCharsRE = regExSpecialChars.replaceAll( ".", "\\\\$0");
final Pattern reCharsREP = Pattern.compile( "[" + regExSpecialCharsRE + "]");

String quoteRegExSpecialChars( String s)
{
    Matcher m = reCharsREP.matcher( s);
    return m.replaceAll( "\\\\$0");
}
4
NeuroDuck

de l’autre côté de la médaille, vous devriez utiliser une expression rationnelle "sans caractère" qui ressemble à ceci si des caractères spéciaux = allChars - number - ABC - espace dans le contexte de votre application.

String regepx = "[^\\s\\w]*";
2
Bo6Bear

La Pattern.quote(String s) fait en quelque sorte ce que vous voulez. Cependant cela laisse un peu à désirer; il n'échappe pas réellement les caractères individuels, mais enveloppe simplement la chaîne avec \Q...\E.

Il n'y a pas de méthode qui fasse exactement ce que vous cherchez, mais la bonne nouvelle est qu'il est en fait assez simple d'échapper à tous les caractères spéciaux d'une expression régulière Java:

regex.replaceAll("[\\W]", "\\\\$0")

Pourquoi ça marche? Eh bien, la documentation de Pattern indique spécifiquement qu'il est permis d'échapper aux caractères non alphabétiques qu'il n'est pas nécessaire d'échapper:

C'est une erreur d'utiliser une barre oblique inverse avant tout caractère alphabétique qui ne dénote pas une construction échappée; ceux-ci sont réservés aux extensions futures du langage à expression régulière. Une barre oblique inverse peut être utilisée avant un caractère non alphabétique, que ce caractère fasse ou non partie d'une construction non échappée.

Par exemple, ; n'est pas un caractère spécial dans une expression régulière. Cependant, si vous y échappez, Pattern interprétera toujours \; comme ;. Voici quelques exemples supplémentaires:

  • > devient \> ce qui équivaut à >
  • [ devient \[ qui est la forme d'échappement de [
  • 8 est toujours 8.
  • \) devient \\\) qui est la forme échappée de \ et ( concaténée.

Remarque: La clé est la définition de "non alphabétique", ce qui dans la documentation signifie en réalité "non - Word ", ou caractères en dehors du jeu de caractères [a-zA-Z_0-9].

2
wheeler

En supposant que vous ayez confiance en la liste des caractères d'échappement Java regex utilisée (ce serait bien si ces caractères étaient exposés dans certains membres de la classe Pattern), vous pouvez utiliser la méthode suivante pour les échapper. s'il est vraiment nécessaire:

private static final char[] escapeChars = { '<', '(', '[', '{', '\\', '^', '-', '=', '$', '!', '|', ']', '}', ')', '?', '*', '+', '.', '>' };

private static String regexEscape(char character) {
    for (char escapeChar : escapeChars) {
        if (character == escapeChar) {
            return "\\" + character;
        }
    }
    return String.valueOf(character);
}
0
brcolow

bien que la réponse soit pour Java, mais le code peut être facilement adapté à partir de cette extension Kotlin String que j'ai proposée (adaptée de celle fournie par @brcolow):

private val escapeChars = charArrayOf(
    '<',
    '(',
    '[',
    '{',
    '\\',
    '^',
    '-',
    '=',
    '$',
    '!',
    '|',
    ']',
    '}',
    ')',
    '?',
    '*',
    '+',
    '.',
    '>'
)

fun String.escapePattern(): String {
    return this.fold("") {
      acc, chr ->
        acc + if (escapeChars.contains(chr)) "\\$chr" else "$chr"
    }
}

fun main() {
    println("(.*)".escapePattern())
}

imprime \(\.\*\)

vérifiez en action ici https://pl.kotl.in/h-3mXZkNE

0
pocesar

Je ne suis pas sûr de bien comprendre votre question, mais je pense que vous devriez regarder Matcher.quoteReplacement ()

0
mkoryak