Когда это делает. не совпадают в Regex?
Я столкнулся со следующей проблемой (упрощенной). Я написал следующее
Pattern pattern = Pattern.compile("Fig.*");
String s = readMyString();
Matcher matcher = pattern.matcher(s);
При чтении одной строки совпадение не совпало, даже если оно начиналось с "Рис. Я проследил проблему до типа изгоев в следующей части строки. Он имел значение кодовой точки 1633 из
(int) charAt(i)
но не соответствует регулярному выражению. Я думаю, что это связано с кодировкой, отличной от UTF-8, где-то во входном процессе.
Javadocs говорят:
Предопределенные классы символов, Любой символ (может или не может совпадать с терминаторами строк)
Предположительно, это не символ в строгом смысле слова, но он все еще является частью строки. Как определить эту проблему?
ОБНОВЛЕНИЕ: Это было связано с (char) 10, что было нелегко заметить. Мой диагноз выше неправильный, и все ответы ниже соответствуют заданному вопросу и полезны.
Ответы
Ответ 1
Символ .
в регулярном выражении Java соответствует любому символу, кроме терминаторов строк, если вы не используете флаг Pattern.DOTALL
при компиляции вашего шаблона.
Чтобы сделать это, вы должны использовать шаблон таким образом:
Pattern p = Pattern.compile("somepattern", Pattern.DOTALL);
Ответ 2
Достаточно легко проверить это:
import java.util.regex.*;
public class Test {
public static void main(String[] args) {
Pattern pattern = Pattern.compile(".");
for (char c = 0; c < 0xffff; c++) {
String text = String.valueOf(c);
if (!pattern.matcher(text).matches()) {
System.out.println((int) c);
}
}
}
}
В моем поле выводится:
10
13
133
8232
8233
Из них 10 и 13 - "\n" и "\ r" соответственно. 133 (U + 0085) является "следующей строкой", 8232 (U + 2028) является "разделителем строк", а 8233 (U + 2029) является "разделителем абзаца".
Обратите внимание, что:
- Это не проверяет символы Юникода за пределами базовой многоязычной плоскости.
- Он использует только параметры по умолчанию
- Кажется, это противоречит вашему опыту характера 1633 (U + 0661)
Ответ 3
В соответствии с документацией .
может иметь 3 несколько разных интерпретации в зависимости от флагов.
По умолчанию
.
исключает ограничители строк, когда DOTALL
и UNIX_LINES
отключены (по умолчанию):
Терминатор линии представляет собой одно- или двухсимвольную последовательность, которая отмечает конец строки входной последовательности символов. Следующие термины распознаются как терминаторы линий:
- Символ новой строки (строка) (
'\n'
), - Символ возврата каретки, за которым сразу следует символ новой строки (
"\r\n"
), - Автономный символ возврата каретки (
'\r'
), - Следующий символ (
'\u0085'
), - Символ разделителя строк (
'\u2028'
) или - Символ разделителя абзаца (
'\u2029'
).
Это означает, что .
эквивалентно [^\n\r\u0085\u2028\u2029]
в этом случае.
Когда режим UNIX_LINES
включен, но режим DOTALL
отключен
.
исключает только \n
, когда включен UNIX_LINES
, но DOTALL
отключен. Это означает, что .
эквивалентно [^\n]
в этом случае.
Если активирован UNIX_LINES
, то единственными признанными терминаторами линии являются символы новой строки.
Когда включен режим DOTALL
Если режим DOTALL
включен, .
будет соответствовать любому символу без исключения.
Регулярное выражение .
соответствует любому символу, кроме терминатора строки, если не указан флаг DOTALL
.
Ответ 4
О работе с символами, не печатающими регулярные выражения, вы можете прочитать эти две статьи:
Есть много сюрпризов, даже если вы работаете именно с UTF.