web-dev-qa-db-fra.com

Échapper aux caractères spéciaux dans les expressions régulières Java

Existe-t-il une méthode en Java ou une bibliothèque open source pour échapper (sans citer) un caractère spécial (méta-caractère), afin de l'utiliser comme expression régulière?

Cela serait très utile pour créer dynamiquement une expression régulière, sans avoir à échapper manuellement chaque caractère.

Par exemple, considérons une expression rationnelle simple telle que \d+\.\d+ qui correspond aux nombres avec une virgule décimale telle que 1.2, ainsi que le code suivant:

String digit = "d";
String point = ".";
String regex1 = "\\d+\\.\\d+";
String regex2 = Pattern.quote(digit + "+" + point + digit + "+");

Pattern numbers1 = Pattern.compile(regex1);
Pattern numbers2 = Pattern.compile(regex2);

System.out.println("Regex 1: " + regex1);

if (numbers1.matcher("1.2").matches()) {
    System.out.println("\tMatch");
} else {
    System.out.println("\tNo match");
}

System.out.println("Regex 2: " + regex2);

if (numbers2.matcher("1.2").matches()) {
    System.out.println("\tMatch");
} else {
    System.out.println("\tNo match");
}

Sans surprise, la sortie produite par le code ci-dessus est:

Regex 1: \d+\.\d+
    Match
Regex 2: \Qd+.d+\E
    No match

C'est-à-dire que regex1 correspond à 1.2 mais que regex2 (construit de manière "dynamique") ne correspond pas (il correspond à la chaîne littérale d+.d+).

Alors, y a-t-il une méthode qui échapperait automatiquement à chaque méta-caractère de regex?

S'il y avait, disons, une méthode escape() statique dans Java.util.regex.Pattern, la sortie de

Pattern.escape('.')

serait la chaîne "\.", mais 

Pattern.escape(',')

devrait simplement produire ",", puisqu'il ne s'agit pas d'un méta-caractère. De même,

Pattern.escape('d')

pourrait produire "\d", puisque 'd' est utilisé pour désigner les chiffres (bien que s'échapper puisse ne pas avoir de sens dans ce cas, puisque 'd' pourrait signifier le littéral 'd', ce qui ne serait pas mal interprété par l'interprète regex, comme ce serait le cas avec '.').

19
PNS

Existe-t-il une méthode en Java ou une bibliothèque open source pour échapper (sans citer) un caractère spécial (méta-caractère), afin de l'utiliser comme expression régulière?

Je ne suis pas sûr à 100% que c'est ce que vous demandez ici. Si vous cherchez un moyen de créer des constantes que vous pouvez utiliser dans vos modèles regex, il suffit de les ajouter avant avec "\\", mais il n'y a pas de fonction Nice Pattern.escape('.') pour vous aider.

Donc, si vous essayez de faire correspondre "\\d" (la chaîne \d au lieu d'un caractère décimal), vous feriez alors:

// this will match on \d as opposed to a decimal character
String matchBackslashD = "\\\\d";
// as opposed to
String matchDecimalDigit = "\\d";

Les 4 barres obliques de la chaîne Java se transforment en 2 barres obliques dans le motif regex. 2 barres obliques inverses dans un motif regex correspond à la barre oblique inversée elle-même. Si vous préférez ajouter un caractère spécial avec une barre oblique inversée, il devient un caractère normal au lieu d'un caractère spécial.

matchPeriod = "\\.";
matchPlus = "\\+";
matchParens = "\\(\\)";
... 

Dans votre message, vous utilisez la méthode Pattern.quote(string) . Vous savez probablement que cela enveloppe votre modèle entre "\\Q" et "\\E" afin que vous puissiez faire correspondre une chaîne même si elle contient un caractère de regex spécial (+, ., \\d, etc.)

23
Gray

J'ai écrit ce modèle:

Pattern SPECIAL_REGEX_CHARS = Pattern.compile("[{}()\\[\\].+*?^$\\\\|]");

Et utilisez-le dans cette méthode:

String escapeSpecialRegexChars(String str) {

    return SPECIAL_REGEX_CHARS.matcher(str).replaceAll("\\\\$0");
}

Ensuite, vous pouvez l'utiliser comme ceci, par exemple:

Pattern toSafePattern(String text)
{
    return Pattern.compile(".*" + escapeSpecialRegexChars(text) + ".*");
}

Nous devions le faire car, après avoir échappé, nous ajoutons des expressions de regex. Sinon, vous pouvez simplement utiliser \Q et \E:

Pattern toSafePattern(String text)
{
    return Pattern.compile(".*\\Q" + text + "\\E.*")
}
23
Ferran Maylinch

La seule façon pour le corrélateur des expressions rationnelles de savoir que vous recherchez un chiffre et non la lettre d est d'échapper à la lettre (\d). Pour taper le caractère d'échappement regex en Java, vous devez l'échapper (pour que \ devienne \\). Il n’ya donc aucun moyen de taper des doubles barres obliques inverses pour les caractères spéciaux de regex.

6
Attila

D'accord avec Gray, car vous aurez peut-être besoin que votre modèle ait à la fois des litrales (\ [ \]) et des méta-caractères ([]). donc avec un utilitaire vous devriez pouvoir échapper à tous les caractères en premier et ensuite vous pouvez ajouter des méta-caractères que vous voulez ajouter sur le même motif.

1
nir

Utilisez cette fonction utilitaire escapeQuotes() afin d'échapper aux chaînes entre Groupes et Ensembles d'une RegualrExpression

Liste des littéraux de regex à échapper <([{\^-=$!|]})?*+.>

public class RegexUtils {
    static String escapeChars = "\\.?![]{}()<>*+-=^$|";
    public static String escapeQuotes(String str) {
        if(str != null && str.length() > 0) {
            return str.replaceAll("[\\W]", "\\\\$0"); // \W designates non-Word characters
        }
        return "";
    }
}

Dans la classe Pattern , le caractère de barre oblique inverse ('\') sert à introduire les constructions échappées. Le littéral de chaîne "\(hello\)" est illégal et conduit à une erreur de compilation. la chaîne littérale "\\(hello\\)" doit être utilisée.

Exemple: La chaîne à faire correspondre (hello) et l'expression régulière avec un groupe est (\(hello\)). Formulaire ici, il vous suffit d'échapper à la chaîne correspondante, comme indiqué ci-dessous. Test Regex online

public static void main(String[] args) {
    String matched = "(hello)", regexExpGrup = "(" + escapeQuotes(matched) + ")";
    System.out.println("Regex : "+ regexExpGrup); // (\(hello\))
}
0
Yash

utilisation

pattern.compile("\"");
String s= p.toString()+"yourcontent"+p.toString();

donnera le résultat comme yourcontent tel quel

0
kavita