Échapper à une chaîne de se faire analyser regex en Java
Question
En Java, supposons que j’ai une variable de chaîne S et que je veuille la chercher dans une autre chaîne T, comme ceci:
if (T.matches(S)) ...
(remarque: la ligne ci-dessus était T.contains () jusqu'à ce que quelques articles indiquent que cette méthode n'utilise pas de regex. Mon mauvais.)
Mais supposons maintenant que S puisse contenir des caractères peu recommandables. Par exemple, prenons S = "[hi". Le crochet gauche entraînera l'échec de l'expression rationnelle. Existe-t-il une fonction que je peux appeler pour échapper à S afin que cela ne se produise pas? Dans ce cas particulier, j’aimerais qu’il soit transformé en "\ [hi" ".
La solution
String.contains n'utilise pas de regex, il n'y a donc aucun problème dans ce cas.
Lorsqu'un regex est requis, plutôt que de rejeter les chaînes avec des caractères spéciaux, utilisez java.util.regex.Pattern.quote pour les échapper.
Autres conseils
Comme Tom Hawtin a déclaré, vous devez citer le motif. Vous pouvez le faire de deux manières (en fait, trois façons, comme le souligne @ diastrophism ):
-
Entourez la chaîne de caractères avec "\ Q" et "\ E", comme:
if (T.matches("\\Q" + S + "\\E"))
-
Utilisez Modèle à la place. Le code ressemblerait à ceci:
Pattern sPattern = Pattern.compile(S, Pattern.LITERAL); if (sPattern.matcher(T).matches()) { /* do something */ }
De cette façon, vous pouvez mettre en cache le motif compilé et le réutiliser. Si vous utilisez plusieurs fois la même expression rationnelle, vous voudrez certainement le faire de cette façon.
Notez que si vous utilisez des expressions régulières pour vérifier si une chaîne se trouve dans une chaîne plus grande, vous devez placer. * au début et à la fin de l'expression. Mais cela ne fonctionnera pas si vous citez le modèle, car il recherchera alors les points réels. Alors, êtes-vous absolument certain de vouloir utiliser des expressions régulières?
Essayez Pattern.quote (String) . Cela corrigera tout ce qui a une signification spéciale dans la chaîne.
Une raison particulière de ne pas utiliser String.indexOf () à la place? De cette manière, il sera toujours interprété comme une chaîne normale plutôt que comme une expression régulière.
Regex utilise le caractère barre oblique inverse '\' pour échapper à un littéral. Étant donné que java utilise également le caractère barre oblique inverse, vous devez utiliser une double bashslash telle que:
String S = "\\[hi"
Cela deviendra la chaîne:
\[hi
qui sera passé à la regex.
Si vous vous souciez uniquement d'une chaîne littérale et que vous n'avez pas besoin de regex, vous pouvez procéder comme suit:
if (T.indexOf("[hi") != -1) {
T.contains () (selon javadoc: http://java.sun.com/javase/6/docs/api/java/lang/String.html ) n’utilise pas d’expression régulière. Contient () des délégués à indexOf () uniquement.
Donc, il n'y a pas de regex utilisés ici. Avez-vous pensé à une autre méthode de String?