Генерирование регулярного выражения из строки
Я хочу создать регулярное выражение из строки, содержащей числа, а затем использовать это как шаблон для поиска похожих строк. Пример:
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.