Я пытаюсь создать приложение, которое сопоставляет шаблон сообщения с сообщением, которое пытается отправить пользователь. Я использую регулярное выражение Java для сопоставления сообщения. Шаблон / сообщение могут содержать специальные символы.
Как мне получить полный список специальных символов, которые нужно экранировать, чтобы мое регулярное выражение работало и совпадало в максимально возможных случаях?
Есть ли универсальное решение для экранирования всех специальных символов в регулярном выражении Java?
\Q
и\E
], считается экранированным» - кроме других\Q
и\E
(которые потенциально могут встречаться в исходном регулярном выражении). Так что лучше использовать то,Pattern.quote
что предлагается здесь, а не изобретать велосипед.\.[]{}()<>*+-=!?^$|
]
и}
) нужно экранировать только после открытия скобок того же типа.[]
скобках некоторые символы (например,+
и-
) иногда работают без выхода.источник
-
внутри[]
может не всегда работать, поскольку оно используется для определения диапазонов. От него безопаснее сбежать. Например, шаблоны[-]
и[-)]
совпадают со строкой,-
но не с[(-)]
.-=!
не обязательно экранировать, это зависит от контекста. Например, как отдельная буква, они работают как постоянное регулярное выражение.Чтобы сбежать, вы можете просто использовать это из Java 1.5 :
Вы точно подберете слово
$test
источник
Согласно странице документации String Literals / Metacharacters , они:
<([{\^-=$!|]})?*+.>
Также было бы круто, если бы этот список где-то в коде ссылался, но я не знаю, где это может быть ...
источник
String escaped = tnk.replaceAll("[\\<\\(\\[\\{\\\\\\^\\-\\=\\$\\!\\|\\]\\}\\)\\?\\*\\+\\.\\>]", "\\\\$0");
s.replaceAll("[\\W]", "\\\\$0")
где\W
обозначает символы, не являющиеся словами.Объединив то, что все сказали, я предлагаю следующее: чтобы список символов, специальных для RegExp, был четко указан в их собственной строке, и избежать необходимости пытаться визуально анализировать тысячи "\\". Мне кажется, это очень хорошо работает:
источник
По предложению @Sorin в документах Java Pattern, похоже, что символы, которые нужно избежать, по крайней мере:
источник
String escaped = regexString.replaceAll("([\\\\\\.\\[\\{\\(\\*\\+\\?\\^\\$\\|])", "\\\\$1");
)
также должно быть экранировано, и в зависимости от того, находитесь ли вы внутри или вне класса символов, может быть больше символов, которые нужно экранировать, и в этом случаеPattern.quote
неплохо справляется с экранированием строки для использования как внутри, так и вне класса символов.Pattern.quote(String s)
Рода делает то , что вы хотите. Однако это оставляет желать лучшего; на самом деле он не экранирует отдельные символы, а просто оборачивает строку\Q...\E
.Не существует метода, который бы делал именно то, что вы ищете, но хорошая новость заключается в том, что на самом деле довольно просто избежать всех специальных символов в регулярном выражении Java:
Почему это работает? Что ж, документация для
Pattern
специально сказано, что разрешено экранировать неалфавитные символы, которые не обязательно экранировать:Например,
;
это не специальный символ в регулярном выражении. Однако, если вы его избежите,Pattern
все равно будет интерпретироваться\;
как;
. Вот еще несколько примеров:>
становится\>
что эквивалентно>
[
становится\[
в ускользнувшую форму[
8
все еще8
.\)
превращается\\\)
в ускользнувшие формы\
и(
сцепленные.Примечание: Ключ является определением «неалфавитным», что в документации на самом деле означает «не- слово » символы или символы вне набора символов
[a-zA-Z_0-9]
.источник
с другой стороны, вы должны использовать регулярное выражение «non-char», которое выглядит так, если специальные символы = allChars - number - ABC - space в контексте вашего приложения.
источник
хотя ответ для Java, но код можно легко адаптировать из этого расширения Kotlin String, которое я придумал (адаптировано из предоставленного @brcolow):
печатает
\(\.\*\)
проверьте это в действии здесь https://pl.kotl.in/h-3mXZkNE
источник
Предполагая, что у вас есть и доверяете (чтобы быть авторитетным) список escape-символов, которые использует регулярное выражение Java (было бы неплохо, если бы эти символы были представлены в каком-либо члене класса Pattern), вы можете использовать следующий метод для экранирования символа, если это действительно необходимо:
источник