Как мне сопоставить любой символ в нескольких строках регулярного выражения? - PullRequest
282 голосов
/ 01 октября 2008

Например, это регулярное выражение

(.*)<FooBar>

будет соответствовать:

abcde<FooBar>

Но как мне заставить его совпадать по нескольким строкам?

abcde
fghij<FooBar>

Ответы [ 21 ]

286 голосов
/ 01 октября 2008

Попробуйте это:

((.|\n)*)<FooBar>

В основном говорится, что «любой символ или символ новой строки» повторяется ноль или более раз.

202 голосов
/ 01 октября 2008

Это зависит от языка, но должен быть модификатор, который вы можете добавить к шаблону регулярных выражений. В PHP это:

/(.*)<FooBar>/s

s в конце заставляет точку совпадать с всеми символами, включая переводы строки.

65 голосов
/ 25 ноября 2011

Если вы используете поиск Eclipse, вы можете включить опцию "DOTALL", чтобы сделать '.' соответствует любому символу, включая разделители строк: просто добавьте «(? s)» в начале строки поиска. Пример:

(?s).*<FooBar>
55 голосов
/ 31 августа 2017

Вопрос в том, может ли . шаблон соответствовать любому символу? Ответ варьируется от двигателя к двигателю. Основное различие заключается в том, используется ли шаблон библиотекой регулярных выражений POSIX или не-POSIX.

Специальное примечание о : они не считаются регулярными выражениями, но . соответствует любому символу там, как и движки на основе POSIX.

Другое примечание по и : . соответствует любому символу по умолчанию ( demo ): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match'); (tokens содержит a abcde\n fghij пункт).

Кроме того, во всех regex грамматика точка соответствует разрывам строки по умолчанию. Boost в ECMAScript грамматике позволяет отключить это с regex_constants::no_mod_m ( source ).

Что касается (на основе POSIX), используйте n option ( demo ): select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual

Двигатели на базе POSIX :

Простое . уже соответствует разрывам строк, нет необходимости использовать какие-либо модификаторы, см. ( demo ).

( демо ), ( демо ), (TRE, база R движок по умолчанию без perl=TRUE, для базы R с perl=TRUE или для stringr / stringi паттернов, используйте встроенный модификатор (?s)) ( demo ) также относитесь к . таким же образом.

Однако , большинство инструментов на основе POSIX обрабатывают ввод построчно. Следовательно, . не соответствует разрывам строк только потому, что они не находятся в области видимости. Вот несколько примеров, как это переопределить:

  • - Есть несколько обходных путей, самый точный, но не очень безопасный - sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/' (H;1h;$!d;x; выкладывает файл в память). Если целые строки должны быть включены, можно рассмотреть sed '/start_pattern/,/end_pattern/d' file (удаление из начала закончится с включенными совпадающими линиями) или sed '/start_pattern/,/end_pattern/{{//!d;};}' file (с исключением совпадающих строк).
  • - perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str" (-0 выгружает весь файл в память, -p печатает файл после применения сценария, заданного -e). Обратите внимание, что использование -000pe приведет к удалению файла и активации «режима абзаца», когда Perl использует последовательные переводы строки (\n\n) в качестве разделителя записей.
  • - grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file. Здесь z разрешает разброс файла, (?s) включает режим DOTALL для шаблона ., (?i) включает режим без учета регистра, \K опускает сопоставленный текст, *? - это ленивый квантификатор, (?=<Foobar>) соответствует местоположению до <Foobar>.
  • - pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file (M здесь разрешает выпадение файла). Примечание pcregrep - хорошее решение для пользователей Mac OS grep.

См. Демонстрации .

Двигатели без POSIX :

  • - Использовать s модификатор PCRE_DOTALL модификатор : preg_match('~(.*)<Foobar>~s', $s, $m) ( demo )
  • - Использовать флаг RegexOptions.Singleline ( демо ):
    - var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
    - var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
  • - Использовать (?s) встроенный параметр: $s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
  • - Использовать модификатор s (или (?s) встроенная версия в начале) ( demo ): /(.*)<FooBar>/s
  • - использовать re.DOTALL (или re.S) флаги или (?s) встроенный модификатор ( demo ): m = re.search(r"(.*)<FooBar>", s, flags=re.S) (а затем if m:, print(m.group(1)))
  • - Использовать модификатор Pattern.DOTALL (или встроенный флаг (?s)) ( demo ): Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
  • - Использовать (?s) модификатор in-pattern ( demo ): regex = /(?s)(.*)<FooBar>/
  • - Использовать модификатор (?s) ( demo ): "(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
  • - Используйте [^] или обходные пути [\d\D] / [\w\W] / [\s\S] ( демо ): s.match(/([\s\S]*)<FooBar>/)[1]
  • (std::regex) Используйте [\s\S] или обходные пути JS ( demo ): regex rex(R"(([\s\S]*)<FooBar>)");
  • - использовать тот же подход, что и в JavaScript, ([\s\S]*)<Foobar>.
  • - Использовать /m MULTILINE модификатор ( демо ): s[/(.*)<Foobar>/m, 1]
  • - Использовать встроенный модификатор (?s) в начале ( demo ): re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
  • - Используйте dotMatchesLineSeparators или (проще) передать встроенный модификатор (?s) в шаблон: let rx = "(?s)(.*)<Foobar>"
  • - То же, что и Swift, (?s) работает проще всего, но вот как можно использовать опцию : NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];
  • , - Использовать модификатор (?s) ( demo ): "(?s)(.*)<Foobar>" (в таблицах Google, =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>"))

ЗАМЕЧАНИЯ ПО (?s):

В большинстве не-POSIX движков можно использовать встроенный модификатор (?s) (или опцию встроенного флага) для принудительного применения . для соответствия разрывам строк.

При размещении в начале шаблона (?s) изменяет поведение всех . в шаблоне. Если (?s) находится где-то после начала, будут затронуты только те ., которые расположены справа от него , если это шаблон, переданный в Python re. В Python re, независимо от местоположения (?s), затрагивается весь шаблон .. Эффект (?s) останавливается с помощью (?-s). Модифицированная группа может использоваться, чтобы влиять только на указанный диапазон шаблона регулярного выражения (например, Delim1(?s:.*?)\nDelim2.* сделает первый .*? совпадением по новым строкам, а второй .* будет соответствовать только остальной части строки).

POSIX note :

В двигателях без регулярных выражений для сопоставления с любым символом можно использовать конструкции [\s\S] / [\d\D] / [\w\W].

В POSIX [\s\S] не соответствует ни одному символу (как в JavaScript или любом не-POSIX-механизме), потому что escape-последовательности регулярного выражения не поддерживаются в выражениях в скобках. [\s\S] анализируется как скобочные выражения, соответствующие одному символу, \ или s или S.

31 голосов
/ 30 июля 2011

В JavaScript используйте /[\S\s]*<Foobar>/. Источник

27 голосов
/ 19 июля 2012

([\s\S]*)<FooBar>

Точка соответствует всем кроме новых строк (\ r \ n). Поэтому используйте \ s \ S, который будет соответствовать ВСЕМ символам.

18 голосов
/ 03 августа 2012

In Ruby Вы можете использовать опцию 'm' (многострочный):

/YOUR_REGEXP/m

См. документацию Regexp на ruby-doc.org для получения дополнительной информации.

10 голосов
/ 06 августа 2018

мы также можем использовать

(.*?\n)*?

чтобы соответствовать всему, включая перевод строки без жадности

Это сделает новую строку необязательной

(.*?|\n)*?
8 голосов
/ 01 октября 2008

"." обычно не соответствует переводу строки. Большинство движков регулярных выражений позволяет добавлять флаг S (также называемый DOTALL и SINGLELINE), чтобы "." также соответствовал символам новой строки. Если это не поможет, вы можете сделать что-то вроде [\S\s].

7 голосов
/ 03 января 2013

Для Eclipse сработало следующее выражение:

Foo

Jadajada Bar "

Регулярное выражение:

Foo[\S\s]{1,10}.*Bar*
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...