В ответах здесь предлагается использовать Pattern.quote
, чтобы избежать специальных символов регулярных выражений.
Проблема с Pattern.quote
заключается в том, что она Pattern.quote
строку целиком, а не каждый отдельный символ.
Это мой случай:
Я получаю строку от пользователя и должен искать ее в документе. Поскольку пользователь не может передавать новые строковые символы (это ошибка в стороннем API, к которому у меня нет доступа), я решил обработать любую последовательность пробелов как "\ s+" и использовать регулярное выражение для поиска документа. Таким образом, пользователь может отправлять простые пробелы вместо символа новой строки.
Например, если документ:
Метасимвол \s используется для поиска символа пробела.
Символом пробелов может быть:
Символ пробела
Символ табуляции
Символ возврата каретки Новый символ линии
Вертикальный символ табуляции
Символ подачи формы
Затем полученная строка
String receivedStr = "The \s metacharacter is used to find a whitespace character. A whitespace character can be:";
следует найти в документе.
Чтобы добиться этого, я хочу процитировать строку, а затем заменить любую последовательность пробелов строкой "\ s+".
Используя следующий код:
receivedStr = Pattern.quote(receivedStr).replaceAll("\\s+", "\\\\s+");
выведите регулярное выражение:
\QThe\s+\s\s+ метасимволом \s+ является\s+ используется \s+ в\s+ найти \s+ а\s+ пробел \s+ символов.\s+ A\s+ пробельные \s+ символ\s+ может \s+ будет:\E
что, конечно, проигнорирует мой добавленный "\s+"
вместо ожидаемого:
\s+\\s\s+ метасимволом \s+ является\s+ используется \s+ в\s+ найти \s+ а\s+ пробел \s+ символов.\s+ A\s+ пробельные \s+ символ\s+ может \s+ быть:
что только ускользает от "\ s" литерала, а не от всей строки.
Есть ли альтернатива Pattern.quote
которая избегает одиночных литералов вместо цельной строки?
Я бы предложил что-то вроде этого:
String re = Stream.of(input.split("\\s+"))
.map(Pattern::quote)
.collect(Collectors.joining("\\s+"));
Это гарантирует, что все будет процитировано (в том числе материал, который в противном случае будет интерпретироваться как внешний вид и может вызвать экспоненциальное раздутие в поиске совпадений), и любой введенный пользователем пробел заканчивается как \s+
.
Пример ввода:
Lorem \\b ipsum \\s dolor (sit) amet.
Вывод:
\QLorem\E\s+\Q\b\E\s+\Qipsum\E\s+\Q\s\E\s+\Qdolor\E\s+\Q(sit)\E\s+\Qamet.\E