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

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

(.*)<FooBar>

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

abcde<FooBar>

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

abcde
fghij<FooBar>

Ответ 1

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

/(.*)<FooBar>/s

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

Ответ 2

Попробуйте следующее:

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

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

Ответ 3

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

(?s).*<FooBar>

Ответ 4

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

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

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

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

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

Движки на основе POSIX:

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

(demo), (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) (демо)
  • - Используйте флаг RegexOptions.Singleline (demo):
    - 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) (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] (demo): 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) в начале (демонстрация): re: = regexp.MustCompile('(?s)(.*)<FooBar>')
  • - используйте dotMatchesLineSeparators или (проще) передайте встроенный модификатор (?s) в шаблон: let rx = "(?s)(.*)<Foobar>"
  • - То же, что и Swift, (?s) работает проще всего, но вот как можно использовать опцию option can be used: 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 примечание:

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

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

Ответ 5

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

Ответ 6

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

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

Ответ 7

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

/YOUR_REGEXP/m

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

Ответ 8

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

(.*?\n)*?

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

Это сделает новую строку опциональной

(.*?|\n)*?

Ответ 9

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

Ответ 10

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

Foo

jadajada Bar "

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

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

Ответ 11

/(.*)<FooBar>/s

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

Ответ 12

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

Ответ 13

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

Ответ 14

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

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

Ответ 16

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

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

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

Ответ 17

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

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

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

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

Ответ 18

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

Ответ 19

в целом. не соответствует символам новой строки, поэтому попробуйте ((.|\n)*)<foobar>

Ответ 20

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

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

   }
...
...
}

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

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

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

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

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

Ответ 21

Часто нам приходится изменять подстроку с несколькими ключевыми словами, разбросанными по строкам, предшествующим подстроке. Рассмотрим элемент 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")

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

Ответ 22

Обычно при поиске трех последовательных строк в 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

Ответ 23

Вариант 1

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

/(.*)<FooBar>/s

Демонстрация 1

Вариант 2

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

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

или

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

или

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

Демонстрация 2

RegEx Circuit

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

enter image description here