Подтвердить что ты не робот

Когда это делает. не совпадают в Regex?

Я столкнулся со следующей проблемой (упрощенной). Я написал следующее

Pattern pattern = Pattern.compile("Fig.*");
String s = readMyString();
Matcher matcher = pattern.matcher(s);

При чтении одной строки совпадение не совпало, даже если оно начиналось с "Рис. Я проследил проблему до типа изгоев в следующей части строки. Он имел значение кодовой точки 1633 из

(int) charAt(i)

но не соответствует регулярному выражению. Я думаю, что это связано с кодировкой, отличной от UTF-8, где-то во входном процессе.

Javadocs говорят:

Предопределенные классы символов, Любой символ (может или не может совпадать с терминаторами строк)

Предположительно, это не символ в строгом смысле слова, но он все еще является частью строки. Как определить эту проблему?

ОБНОВЛЕНИЕ: Это было связано с (char) 10, что было нелегко заметить. Мой диагноз выше неправильный, и все ответы ниже соответствуют заданному вопросу и полезны.

4b9b3361

Ответ 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.