Список всех специальных символов, которые должны быть экранированы в регулярном выражении
Я пытаюсь создать приложение, соответствующее шаблону сообщения, с сообщением, которое пользователь пытается отправить. Я использую Java regex для сопоставления сообщения. Шаблон/сообщение может содержать специальные символы.
Как мне получить полный список специальных символов, которые нужно экранировать, чтобы мое регулярное выражение работало и соответствовало максимально возможным случаям?
Существует ли универсальное решение для экранирования всех специальных символов в Java regex?
Ответы
Ответ 1
Вы можете посмотреть на javadoc класса Pattern: http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html
Вам нужно избегать любого перечисленного там символа, если вы хотите обычный символ, а не особое значение.
В качестве более простого решения вы можете поместить шаблон между \Q и\E - все, что находится между ними, считается экранированным.
Ответ 2
- Java-символы, которые необходимо экранировать в регулярных выражениях:
\.[]{}()<>*+-=!?^$|
- Две закрывающие скобки (
]
и }
) необходимо экранировать только после открытия скобки того же типа. - В
[]
-brackets некоторые символы (например, +
и -
) иногда работают без экранирования.
Ответ 3
Чтобы сбежать, вы можете просто использовать это из Java 1.5:
Pattern.quote("$test");
Вы точно найдете слово $test
Ответ 4
Согласно странице документации String Literals/Metacharacters, это:
<([{\^-=$!|]})?*+.>
Также было бы здорово, если бы этот список ссылался где-то в коде, но я не знаю, где это могло бы быть...
Ответ 5
В представлении @Sorin о документах Java-паттерна, похоже, что символы для выхода не менее:
\.[{(*+?^$|
Ответ 6
Объединив все сказанное, я предлагаю следующее: сохранить список символов специально для RegExp, явно указанный в их собственной String, и не пытаться визуально разобрать тысячи "\\". Мне кажется, это работает очень хорошо:
final String regExSpecialChars = "<([{\\^-=$!|]})?*+.>";
final String regExSpecialCharsRE = regExSpecialChars.replaceAll( ".", "\\\\$0");
final Pattern reCharsREP = Pattern.compile( "[" + regExSpecialCharsRE + "]");
String quoteRegExSpecialChars( String s)
{
Matcher m = reCharsREP.matcher( s);
return m.replaceAll( "\\\\$0");
}
Ответ 7
Pattern.quote(String s)
делает то, что вы хотите. Однако это оставляет желать лучшего; на самом деле он не экранирует отдельные символы, а просто переносит строку с помощью \Q...\E
Не существует метода, который делает именно то, что вы ищете, но хорошая новость заключается в том, что на самом деле довольно просто экранировать все специальные символы в регулярном выражении Java:
regex.replaceAll("[\\W]", "\\\\$0")
Почему это работает? Что ж, в документации для Pattern
определенно сказано, что допустимо экранировать не алфавитные символы, которые не обязательно должны быть экранированы:
Ошибочно использовать обратную косую черту перед любым буквенным символом, который не обозначает экранированную конструкцию; они зарезервированы для будущих расширений языка регулярных выражений. Обратная косая черта может использоваться до не алфавитного символа независимо от того, является ли этот символ частью неэкранированной конструкции.
Так, например, ;
не является специальным символом в регулярном выражении. Однако, если вы избежите этого, Pattern
все равно будет интерпретировать \;
как ;
, Вот еще несколько примеров:
-
>
становится \>
что эквивалентно >
-
[
становится \[
который является экранированной формой [
-
8
все еще 8
. -
\)
становится \\\)
что является экранированными формами \
и (
сцеплено.
Примечание. Ключом является определение "не алфавитного", которое в документации действительно означает "не-словесные" символы или символы вне набора символов [a-zA-Z_0-9]
.
Ответ 8
на другой стороне монеты, вы должны использовать регулярное выражение "не char", которое выглядит так, если специальные символы = allChars - number - ABC - пространство в контексте вашего приложения.
String regepx = "[^\\s\\w]*";
Ответ 9
Предполагая, что у вас есть и доверяете (чтобы быть авторитетным) список escape-символов, которые использует регулярное выражение Java (было бы неплохо, если бы эти символы были представлены в некотором члене класса Pattern), вы можете использовать следующий метод для экранирования символа, если это действительно необходимо:
private static final char[] escapeChars = { '<', '(', '[', '{', '\\', '^', '-', '=', '$', '!', '|', ']', '}', ')', '?', '*', '+', '.', '>' };
private static String regexEscape(char character) {
for (char escapeChar : escapeChars) {
if (character == escapeChar) {
return "\\" + character;
}
}
return String.valueOf(character);
}
Ответ 10
хотя ответ и для Java, но код можно легко адаптировать из этого расширения Kotlin String, которое я придумал (адаптировано из предоставленного @brcolow):
private val escapeChars = charArrayOf(
'<',
'(',
'[',
'{',
'\\',
'^',
'-',
'=',
'$',
'!',
'|',
']',
'}',
')',
'?',
'*',
'+',
'.',
'>'
)
fun String.escapePattern(): String {
return this.fold("") {
acc, chr ->
acc + if (escapeChars.contains(chr)) "\\$chr" else "$chr"
}
}
fun main() {
println("(.*)".escapePattern())
}
печатает \(\.\*\)
проверьте это в действии здесь https://pl.kotl.in/h-3mXZkNE
Ответ 11
Не уверен, что я полностью понимаю ваш вопрос, но я думаю, вы должны смотреть на
Matcher.quoteReplacement()