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

StackOverflow https://stackoverflow.com/questions/159118

  •  03-07-2019
  •  | 
  •  

Вопрос

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

(.*)<FooBar>

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

abcde<FooBar>

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

abcde
fghij<FooBar>
Это было полезно?

Решение

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

/(.*)<FooBar>/s

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

Другие советы

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

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

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

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

(?s).*<FooBar>

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

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

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

Также во всех В грамматиках регулярных выражений точка по умолчанию соответствует разрыву строки.Грамматика 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:

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

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

Однако, Большинство инструментов на базе 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) (демо)
  • - Использовать 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) встроенная версия в начале) (демо): /(.*)<FooBar>/s
  • - Использовать re.DOTALL (или re.S) флаги или (?s) встроенный модификатор (демо): m = re.search(r"(.*)<FooBar>", s, flags=re.S) (а потом if m:, print(m.group(1)))
  • - Использовать Pattern.DOTALL модификатор (или встроенный (?s) флаг) (демо): Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
  • - Использовать (?s) модификатор в шаблоне (демо): regex = /(?s)(.*)<FooBar>/
  • - Использовать (?s) модификатор (демо): "(?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 (демо): regex rex(R"(([\s\S]*)<FooBar>)");
  • - Используйте тот же подход, что и в JavaScript, ([\s\S]*)<Foobar>.
  • - Использовать /m МНОГОЛИНЕЙНЫЙ модификатор (демо): s[/(.*)<Foobar>/m, 1]
  • - Используйте встроенный модификатор (?s) в начале (демо): re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
  • - Использовать dotMatchesLineSeparators или (проще) передать (?s) встроенный модификатор шаблона: let rx = "(?s)(.*)<Foobar>"
  • - То же, что и Свифт, (?s) работает проще всего, но вот как вариант можно использовать: NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];
  • , - Использовать (?s) модификатор (демо): "(?s)(.*)<Foobar>" (в таблицах Google, =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>"))

ПРИМЕЧАНИЯ К (?s):

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

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

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

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

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

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

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

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

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

/YOUR_REGEXP/m

Видеть документация по регулярному выражению на Ruby-doc.org для получения дополнительной информации.

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

(.*?\n)*?

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

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

(.*?|\n)*?

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

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

Фу

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

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

Foo[\S\s]{1,10}.*Bar*
/(.*)<FooBar>/s

s приводит к тому, что точка (.) соответствует возврату каретки

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

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

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

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

Решение:

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

пример:

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

Источник:

http://dreamluverz.com/developers-tools/regex-match-all-включая-new-line http://php.net/manual/en/reference.pcre.pattern.modifiers.php

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

В этом случае данное регулярное выражение будет соответствовать всей строке, поскольку присутствует «<FooBar>».В зависимости от особенностей реализации регулярного выражения значение $1 (полученное из "(.*)") будет либо "fghij", либо "abcde fghij".Как говорили другие, некоторые реализации позволяют вам контролировать «". Сопоставят Newline, давая вам выбор.

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

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

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

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

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

В 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>

Я хотел сопоставить определенный блок if в Java

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

   }
...
...
}

Если я использую регулярное выражение

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")

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top