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

244

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

(.*)<FooBar>

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

abcde<FooBar>

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

abcde
fghij<FooBar>
  • 1
    Уточнить; Первоначально я использовал Eclipse, чтобы найти и заменить несколько файлов. Из ответов ниже я обнаружил, что моей проблемой был инструмент, а не шаблон регулярных выражений.
  • 2
    Ваш флаг «Затмение» должен быть удален, потому что тот, кто ищет решение для затмения, найдет этот вопрос (как я), а затем найдет решение без затмения, как принятое.
Показать ещё 1 комментарий
Теги:
multiline

20 ответов

193
Лучший ответ

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

/(.*)<FooBar>/s

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

  • 0
    а что если я хотел просто новую строку, а не все символы?
  • 3
    @Grace: использовать \ n для соответствия новой строки
Показать ещё 9 комментариев
240

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

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

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

  • 3
    Это зависит от языка и / или инструмента, который вы используете. Пожалуйста, дайте нам знать, что вы используете, например, Perl, PHP, CF, C #, sed, awk и т. Д.
  • 31
    В зависимости от окончания строки вам может понадобиться ((.|\n|\r)*)<FooBar>
Показать ещё 5 комментариев
61

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

(?s).*<FooBar>
  • 8
    Это не зависит от затмения, должно работать где угодно.
  • 0
    Не где-нибудь, только в регулярных выражениях, поддерживающих встроенные модификаторы, и, конечно, не в Ruby, где (?s) => (?m)
Показать ещё 1 комментарий
38

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

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

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

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

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

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

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

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

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

  • - Есть несколько обходных путей, самый точный, но не очень безопасный, это sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/' 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 приведет к -000pe файла и активированию "режима абзаца", где Perl использует последовательные переводы строки (\n\n) в качестве разделителя записей.
  • - файл grep -poz '(?si)abc\K.*?(?=<Foobar>)' file. Здесь, z разрешает растушевку файла, (?s) включает режим DOTALL для . pattern, (?i) включает режим без учета регистра, \K опускает соответствующий текст, *? является ленивым квантификатором, (?=<Foobar>) соответствует местоположению перед <Foobar>.
  • - pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file (M разрешает выпадение файла). Примечание pcregrep является хорошим решением для Mac OS grep пользователей.

Смотрите демоверсии.

Не -p OSIX-движки:

  • - Использовать модификатор 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 = "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) в модификаторе attern -p (демо): 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 MULTILINE (демо): s[/(.*)<Foobar>/m, 1]
  • - Использовать встроенный модификатор (?s) в начале (демо): re: = regexp.MustCompile('(?s)(.*)<FooBar>')
  • - Используйте dotMatchesLineSeparators или (проще) передать встроенный модификатор (?s) в шаблон: let rx = "(?s)(.*)<Foobar>"
  • - То же, что и Swift, (?s) работает проще всего, но вот как этот параметр можно использовать: NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];
  • , - Использовать модификатор (?s) (демо): "(?s)(.*)<Foobar>" (в таблицах Google, =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>"))

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

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

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

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

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

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

  • 4
    Вы должны сослаться на этот отличный обзор со страницы своего профиля или что-то (+1).
  • 1
    Возможно, вы захотите добавить это к элементу boost : в пространстве имен regex_constants flag_type_'s: perl = ECMAScript = JavaScript = JScript = :: boost :: regbase :: normal = 0, который по умолчанию равен Perl. Программисты установят определение базового флага #define MOD regex_constants::perl | boost::regex::no_mod_s | boost::regex::no_mod_m для их флагов регулярных выражений, чтобы отразить это. А арбитор всегда встроенные модификаторы. Где (?-sm)(?s).* Сбрасывает.
Показать ещё 2 комментария
30

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

  • 2
    По этой ссылке: «JavaScript и VBScript не имеют возможности сделать точки, соответствующие символу разрыва строки. В этих языках вы можете использовать класс символов, такой как [\ s \ S], для соответствия любому символу». Вместо. используйте вместо этого [\ s \ S] (совпадение пробелов и не пробелов).
23

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

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

  • 0
    Это решит проблему, если вы используете Objective-C [text rangeOfString:regEx options:NSRegularExpressionSearch] . Спасибо!
  • 0
    Это работает в поиске и замене IntelliJ, спасибо.
Показать ещё 1 комментарий
18

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

/YOUR_REGEXP/m

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

10

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

(.*?\n)*?

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

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

(.*?|\n)*?
8

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

7

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

Foo

jadajada Bar "

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

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

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

  • 0
    Похоже, это неверно (Chrome): text.match (/ a / s) SyntaxError: неверные флаги, предоставленные конструктору RegExp 's'
  • 0
    Потому что это не поддерживается в движках JavaScript RegEx. Флаги s существуют в PCRE, самом полном движке (доступно на Perl и PHP). PCRE имеет 10 флагов (и множество других функций), в то время как JavaScript имеет только 3 флага ( gmi ).
3

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

  • 1
    Разве это не должны быть обратные слеши?
  • 0
    Они идут в конце регулярного выражения, а не в пределах. Пример: / blah / s
Показать ещё 1 комментарий
3

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

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

3

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

2

Решение:

Использовать шаблонный модификатор 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

1

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

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

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

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

  • 0
    Я тоже использую .NET и (\s|\S) похоже, помогает мне!
  • 0
    @VamshiKrishna В .NET используйте (?s) для создания . соответствовать любым символам. Не используйте (\s|\S) что замедлит производительность.
1

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

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

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

0

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

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

0

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

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

   }
...
...
}

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

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

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

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

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

0

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

  • 1
    Нет, не делай этого. Если вам нужно сопоставить что-либо, включая разделители строк, используйте модификатор DOTALL (aka / s или SingleLine). Мало того, что взлом (. | \ N) делает регулярное выражение менее эффективным, это даже не правильно. По крайней мере, он должен соответствовать \ r (возврат каретки), а также \ n (перевод строки). Есть и другие символы разделителя строк, хотя они используются редко. Но если вы используете флаг DOTALL, вам не нужно беспокоиться о них.
  • 1
    \ R - независимое от платформы совпадение для новых строк в Eclipse.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню