На этом шаге мы рассмотрим использование флага re.DOTALL при построении регулярных выражений.
Вы пытаетесь провести поиск по блоку текстов с использованием регулярного выражения, но вам нужно, чтобы совпадение охватывало несколько строк.
Эта проблема обычно возникает в шаблонах, которые используют точку (.) для поиска совпадения с любым символом. Многие забывают, что точка не может совпадать с символом новой строки. Например, вы пытаетесь найти совпадения в комментариях в стиле языка С:
>>> comment = re.compile(r'/\*(.*?)\*/') >>> text1 = '/* this is a comment */' >>> text2 = '''/* this is a multiline comment */ ''' >>> comment.findall(text1) [' this is a comment '] >>> comment.findall(text2) [] >>>
Чтобы исправить проблему, вам нужно добавить поддержку символов новой строки. Например:
>>> comment = re.compile(r'/\*((?:.|\n)*?)\*/') >>> comment.findall(text2) [' this is a\n multiline comment '] >>>
В этом шаблоне (?:.|\n) определяет незахватывающую группу (то есть выражение определяет группу для целей поиска совпадений, но эта группа не
захватывается и не подсчитывается).
Функция re.compile() принимает полезный в данном случае флаг re.DOTALL. Он заставляет символ "." в регулярном выражении совпадать с любыми символами, включая символ новой строки. Например:
>>> comment = re.compile(r'/\*(.*?)\*/', re.DOTALL) >>> comment.findall(text2) [' this is a\n multiline comment '] >>>
Использование флага re.DOTALL отлично работает в простых случаях, но это может давать сбои при работе с очень сложными шаблонами или сочетанием отдельных регулярных выражений, которые должны объединяться друг с другом для токенизации. Если у вас есть выбор, обычно лучше определить шаблон регулярного выражения, так чтобы он работал правильно без необходимости в дополнительных флагах.
На следующем шаге мы рассмотрим нормализацию текста в Unicode к стандартному представлению.