Список всех специальных символов, которые должны быть экранированы в регулярном выражении

Я пытаюсь создать приложение, соответствующее шаблону сообщения, с сообщением, которое пользователь пытается отправить. Я использую 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()