Генерирование регулярного выражения из строки

Я хочу создать регулярное выражение из строки, содержащей числа, а затем использовать это как шаблон для поиска похожих строк. Пример:

String s = "Page 3 of 23"

Если я заменю все цифры на \d

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < s.length(); i++) {
    char c = s.charAt(i);
    if (Character.isDigit(c)) {
        sb.append("\\d"); // backslash d
    } else {
        sb.append(c);
        }
    }

    Pattern numberPattern = Pattern.compile(sb.toString());

//    Pattern numberPattern = Pattern.compile("Page \d of \d\d");

Я могу использовать это, чтобы соответствовать аналогичным строкам (например, "Page 7 of 47"). Моя проблема заключается в том, что если я наивно выполняю это, некоторые метасимволы, такие как (){}- и т.д., Не будут экранированы. Есть ли библиотека для этого или исчерпывающий набор символов для регулярных выражений, которые я должен и не должен убегать? (Я могу попытаться извлечь их из Javadocs, но я беспокоюсь о чем-то недостающем).

В качестве альтернативы есть библиотека, которая уже делает это (я на данном этапе не хочу использовать полное решение для обработки естественного языка).

ПРИМЕЧАНИЕ: теперь отредактированный ответ @dasblinkenlight работает для меня!

Ответ 1

Библиотека Java regexp предоставляет эту функциональность:

String s = Pattern.quote(orig);

Строка "quoted" будет содержать все метасимволы. Во-первых, избегайте вашей строки, а затем пройдите через нее и замените цифры на \d, чтобы сделать регулярное выражение. Поскольку библиотека regex использует \Q и \E для цитирования, вам нужно заключить свою часть регулярного выражения в обратные кавычки \E и \Q.

Одна вещь, которую я бы изменил в вашей реализации, - это алгоритм замены: вместо замены по-символу я бы заменил цифры в группах. Это дало бы выражение, выраженное из Page 3 of 23 строк соответствия, таких как Page 13 of 23 и Page 6 of 8.

String p = Pattern.quote(orig).replaceAll("\\d+", "\\\\E\\\\d+\\\\Q");

Это произведет "\QPage \E\d+\Q of \E\d+\Q\E" независимо от того, какие номера страниц и числа были там изначально. Вывод нуждается только в одном, а не в двух слэшах в \d, потому что результат напрямую подается на механизм regex, минуя компилятор Java.