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

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

(.*)<FooBar>

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

abcde<FooBar>

Но как мне сделать так, чтобы он совпадал по нескольким строкам?

abcde
fghij<FooBar>

26 ответов

Решение

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

/(.*)<FooBar>/s

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

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

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

Это в основном говорит, что "любой символ или перевод строки" повторяется ноль или более раз.

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

Особое примечание о шаблонах lua: они не считаются регулярными выражениями, но . соответствует любому символу там, так же как движки на основе POSIX.

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

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

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

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

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

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

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

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

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

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

POSIX примечание:

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

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

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

(?s).*<FooBar>

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

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

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

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

(.*?\n)*?

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

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

(.*?|\n)*?

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

/YOUR_REGEXP/m

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

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

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

Foo

Джададжада Бар "

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

Foo[\S\s]{1,10}.*Bar*

Это работает для меня и является самым простым:

      (\X*)<FooBar>

В блокноте ++ вы можете использовать это

      <table (.|\r\n)*</table>

Он будет соответствовать всей таблице, начиная с

строки и столбцы

Вы можете сделать его жадным, используя следующее, таким образом он будет соответствовать первой, второй и так далее таблицам, а не всем сразу

      <table (.|\r\n)*?</table>

Обратите внимание, что (.|\n)* может быть менее эффективным, чем (например) [\s\S]* (если регулярные выражения вашего языка поддерживают такие побеги) и чем найти, как указать модификатор, который делает. также соответствуйте новым строкам. Или вы можете пойти с POSIXy альтернативами, такими как [[:space:][:^space:]]*,

Используйте RegexOptions.Singleline, это меняет значение. включить переводы строки

Regex.Replace(content, searchText, replaceText, RegexOptions.Singleline);

/(.*)<FooBar>/s

s заставляет Dot (.) соответствовать возврату каретки

В регулярном выражении на основе Java вы можете использовать [\s\S]

В общем-то. не соответствует переводу строки, поэтому попробуйте ((.|\n)*)<foobar>

Решение:

Используйте модификатор шаблона sU, чтобы получить желаемое совпадение в PHP.

пример:

preg_match('/(.*)/sU',$content,$match);

Источник:

http://dreamluverz.com/developers-tools/regex-match-all-including-new-line http://php.net/manual/en/reference.pcre.pattern.modifiers.php

В Javascript вы можете использовать [^]* для поиска от нуля до бесконечных символов, включая разрывы строк.

$("#find_and_replace").click(function() {
  var text = $("#textarea").val();
  search_term = new RegExp("[^]*<Foobar>", "gi");;
  replace_term = "Replacement term";
  var new_text = text.replace(search_term, replace_term);
  $("#textarea").val(new_text);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="find_and_replace">Find and replace</button>
<br>
<textarea ID="textarea">abcde
fghij&lt;Foobar&gt;</textarea>

Пытаться: .*\n*.*<FooBar>предполагая, что вы также разрешаете пустые символы новой строки. Поскольку вы разрешаете любому персонажу, не включая ничего до<FooBar>.

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

В этом случае данное регулярное выражение будет соответствовать всей строке, поскольку присутствует "". В зависимости от особенностей реализации регулярного выражения значение $1 (полученное из "(.*)") Будет либо "fghij", либо "abcde\nfghij". Как уже говорили другие, некоторые реализации позволяют вам контролировать, стоит ли "." будет соответствовать новой строке, давая вам выбор.

Основанное на строке регулярное выражение обычно используется для таких вещей, как egrep.

У меня была та же проблема, и я решил ее, вероятно, не лучшим образом, но она работает. Я заменил все разрывы строк, прежде чем я сделал свой реальный матч:

mystring= Regex.Replace(mystring, "\r\n", "")

Я манипулирую HTML, поэтому разрывы строк не имеют для меня большого значения в этом случае.

Я попробовал все предложения выше без удачи, я использую.Net 3.5 FYI

Обычно при поиске трех последовательных строк в Powershell это выглядит так:

$file = get-content file.txt -raw

$pattern = 'lineone\r\nlinetwo\r\nlinethree\r\n'     # "windows" text
$pattern = 'lineone\nlinetwo\nlinethree\n'           # "unix" text
$pattern = 'lineone\r?\nlinetwo\r?\nlinethree\r?\n'  # both

$file -match $pattern

# output
True

Как ни странно, это будет текст unix в приглашении, но текст Windows в файле:

$pattern = 'lineone
linetwo
linethree
'

Вот способ распечатать окончания строк:

'lineone
linetwo
linethree
' -replace "`r",'\r' -replace "`n",'\n'

# output
lineone\nlinetwo\nlinethree\n

Я хотел, чтобы соответствовать конкретный, если блок в Java

   ...
   ...
   if(isTrue){
       doAction();

   }
...
...
}

Если я использую regExp

if \(isTrue(.|\n)*}

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

if \(!isTrue([^}.]|\n)*}

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

Часто нам нужно изменить подстроку с несколькими ключевыми словами, разбросанными по строкам, предшествующим подстроке. Рассмотрим элемент xml:

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>81</PercentComplete>
</TASK>

Предположим, что мы хотим изменить 81, на другое значение, скажем, 40. Сначала определите .UID.21..UID., затем пропустите все символы, включая \n до .PercentCompleted., Шаблон регулярного выражения и спецификация замены:

String hw = new String("<TASK>\n  <UID>21</UID>\n  <Name>Architectural design</Name>\n  <PercentComplete>81</PercentComplete>\n</TASK>");
String pattern = new String ("(<UID>21</UID>)((.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
String replaceSpec = new String ("$1$2$440$6");
//note that the group (<PercentComplete>) is $4 and the group ((.|\n)*?) is $2.

String  iw = hw.replaceFirst(pattern, replaceSpec);
System.out.println(iw);

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>40</PercentComplete>
</TASK>

Подгруппа (.|\n) вероятно пропавшая группа $3, Если мы сделаем это без захвата (?:.|\n) тогда $3 является (<PercentComplete>), Так что картина и replaceSpec так же может быть:

pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")

и замена работает правильно, как и раньше.

Опция 1

Один из способов - использовать s флаг (как в принятом ответе):

/(.*)<FooBar>/s

Демо 1

Вариант 2

Второй способ - использовать m (многострочный) флаг и любой из следующих шаблонов:

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

или

/([\d\D]*)<FooBar>/m

или

/([\w\W]*)<FooBar>/m

Демо 2

Цепь RegEx

jex.im визуализирует регулярные выражения:

Другие вопросы по тегам