Есть ли у Java встроенный способ избежать произвольного текста, чтобы он мог быть включен в регулярное выражение? Например, если мои пользователи вводят "5 долларов США", я бы хотел совместить это, а не "5" после окончания ввода.
Как избежать текста для регулярного выражения в Java
Ответ 1
Так как Java 1.5, да:
Pattern.quote("$5");
Ответ 2
Разница между Pattern.quote
и Matcher.quoteReplacement
мне не было ясно, прежде чем я увидел следующий пример
s.replaceFirst(Pattern.quote("text to replace"),
Matcher.quoteReplacement("replacement text"));
Ответ 3
Возможно, слишком поздно ответить, но вы также можете использовать Pattern.LITERAL
, который будет игнорировать все специальные символы при форматировании:
Pattern.compile(textToFormat, Pattern.LITERAL);
Ответ 4
Я думаю, что вам нужно \Q$5\E
. Также см. Pattern.quote(s)
, введенный в Java5.
Подробнее см. Pattern javadoc.
Ответ 5
Прежде всего, если
- вы используете replaceAll()
- НЕ используйте Matcher.quoteReplacement()
- текст, подлежащий замене, включает в себя $1
он не поместит 1 в конец. Он будет искать регулярное выражение поиска для первой сопоставимой группы и суб THAT. Что означает $1, $2 или $3 в заменяющем тексте: сопоставление групп с шаблоном поиска.
Я часто подключаю длинные строки текста к файлам .properties, а затем создаю объекты электронной почты и тела из них. В самом деле, это, по-видимому, является способом по умолчанию для i18n в Spring Framework. Я помещал теги XML в качестве заполнителей в строки, и я использую replaceAll() для замены тегов XML значениями во время выполнения.
Я столкнулся с проблемой, когда пользователь вводил цифру доллара и центов со знаком доллара. replaceAll() захлебнулся, при этом в stracktrace отображается следующее:
java.lang.IndexOutOfBoundsException: No group 3
at java.util.regex.Matcher.start(Matcher.java:374)
at java.util.regex.Matcher.appendReplacement(Matcher.java:748)
at java.util.regex.Matcher.replaceAll(Matcher.java:823)
at java.lang.String.replaceAll(String.java:2201)
В этом случае пользователь ввел "$ 3" где-то на своем входе, а replaceAll() пошел в поисковое регулярное выражение для третьей сопоставимой группы, не нашел ее и не потерял.
Дано:
// "msg" is a string from a .properties file, containing "<userInput />" among other tags
// "userInput" is a String containing the user input
вместо
msg = msg.replaceAll("<userInput \\/>", userInput);
с
msg = msg.replaceAll("<userInput \\/>", Matcher.quoteReplacement(userInput));
решил проблему. Пользователь может вводить любые символы, включая знаки доллара, без проблем. Он вел себя так, как вы ожидали.
Ответ 6
Чтобы иметь защищенный шаблон, вы можете заменить все символы на "\\\\", кроме цифр и букв. И после этого вы можете поместить в этот защищенный шаблон свои специальные символы, чтобы заставить этот шаблон работать не как глупый цитируемый текст, а действительно как паттен, но ваш собственный. Без специальных символов пользователя.
public class Test {
public static void main(String[] args) {
String str = "y z (111)";
String p1 = "x x (111)";
String p2 = ".* .* \\(111\\)";
p1 = escapeRE(p1);
p1 = p1.replace("x", ".*");
System.out.println( p1 + "-->" + str.matches(p1) );
//.*\ .*\ \(111\)-->true
System.out.println( p2 + "-->" + str.matches(p2) );
//.* .* \(111\)-->true
}
public static String escapeRE(String str) {
//Pattern escaper = Pattern.compile("([^a-zA-z0-9])");
//return escaper.matcher(str).replaceAll("\\\\$1");
return str.replaceAll("([^a-zA-Z0-9])", "\\\\$1");
}
}
Ответ 7
Pattern.quote( "blabla" ) прекрасно работает.
Образец Pattern.quote() работает красиво. Он заключает предложение с символами "\Q" и "\E", и если он убегает "\ Q" и "\ E". Однако, если вам нужно выполнить экстренное выполнение обычного выражения (или пользовательское экранирование), вы можете использовать этот код:
String someText = "Some/s/wText*/,**";
System.out.println(someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));
Этот метод возвращает: Some/\ s/wText */\, **
Код, например, и тесты:
String someText = "Some\\E/s/wText*/,**";
System.out.println("Pattern.quote: "+ Pattern.quote(someText));
System.out.println("Full escape: "+someText.replaceAll("[-\\[\\]{}()*+?.,\\\\\\\\^$|#\\\\s]", "\\\\$0"));