Есть ли у Java встроенный способ избежать произвольного текста, чтобы он мог быть включен в регулярное выражение? Например, если мои пользователи вводят "5 долларов США", я бы хотел совместить это, а не "5" после окончания ввода.
Так как Java 1.5, да:
Pattern.quote("$5");
Разница между Pattern.quote
и Matcher.quoteReplacement
мне не было ясно, прежде чем я увидел следующий пример
s.replaceFirst(Pattern.quote("text to replace"),
Matcher.quoteReplacement("replacement text"));
Pattern.quote
заменяет специальные символы в строках поиска регулярных выражений, например. | + () И т. Д., А Matcher.quoteReplacement
заменяет специальные символы в строках замены, например \ 1 для обратных ссылок.
Возможно, слишком поздно ответить, но вы также можете использовать Pattern.LITERAL
, который будет игнорировать все специальные символы при форматировании:
Pattern.compile(textToFormat, Pattern.LITERAL);
Pattern.CASE_INSENSITIVE
Я думаю, что вам нужно \Q$5\E
. Также см. Pattern.quote(s)
, введенный в Java5.
Подробнее см. Pattern javadoc.
Прежде всего, если
он не поместит 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));
решил проблему. Пользователь может вводить любые символы, включая знаки доллара, без проблем. Он вел себя так, как вы ожидали.
Чтобы иметь защищенный шаблон, вы можете заменить все символы на "\\\\", кроме цифр и букв. И после этого вы можете поместить в этот защищенный шаблон свои специальные символы, чтобы заставить этот шаблон работать не как глупый цитируемый текст, а действительно как паттен, но ваш собственный. Без специальных символов пользователя.
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");
}
}
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"));
\Q
и\E
Это может привести к неожиданным результатам, например,Pattern.quote("*.wav").replaceAll("*",".*")
к\Q.*.wav\E
а не.*\.wav
, как и следовало ожидать.