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

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

То, что у меня есть, до сих пор работает с ограниченным количеством пробелов |,

У меня проблемы с той частью, которая определяет, что достигнута линия, которая не соответствует требованиям. По какой-то причине \n\s*[^\|] не делает трюк. Что я сейчас делаю, так это следующее:

(?P<terminating>
    \n(             # when newline is encountered...
        [^\|\s]         #   check if next character is not: (| or space)
        |
        [\s][^\|\s]     #   check if next characters are not: space + (| or space)
        |
        [\s][\s][^\|\s] #   check if next characters are not: space + space + (| or space)... And so on....
    )
    |
    $
)

Это очевидно работает только для двух пробелов. Я хотел бы сделать эту работу для произвольного количества пробелов. Я посмотрел на рекурсию, но, похоже, в этом случае это довольно тяжелое оружие. Вот теперь мой вопрос: почему \n\s*[^\|] не работает, и есть ли другой способ решить это без рекурсии?


Ниже приведен пример ввода и полученного соответствия, которое я хотел бы получить:

Строка ввода:

Lorem ipsum dolor sit amet, 
consectetur adipisicing 
elit, 
|sed do 
        |eiusmod tempor incididunt 
     |ut labore et dolore magna aliqua.
Ut enim ad minim veniam, 
quis nostrud exercitation 
ullamco laboris nisi ut 
aliquip ex ea commodo consequat.

Вывод - одна строка с содержимым:

|sed do\n        |eiusmod tempor incididunt\n     |ut labore et dolore magna aliqua.

Я не хочу три матча с каждой из линий, которые имеют | в этом.

4 ответа

Решение

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

n\s*[^\|\s]

Хотя я не совсем уверен, почему это так, я случайно наткнулся на это. Я был бы признателен, если бы кто-то мог объяснить причину этого.

Полное выражение теперь выглядит следующим образом:

'/
    (?:
        (^|\n)\s*\|
    )
    (?P<main>
        .*?
    )
    (?=
        \n\s*[^\|\s]
        |
        $
    )
/sx'

Если вы используете PHP, это должно сделать это:

(?m)^\h*\|.*(?:\R\h*\|.*)*

Некоторые интересные места:

  • \h соответствует горизонтальному пробелу, что означает пробел и символы табуляции

  • \R соответствует разделителю строк, будь то \n, \r\n, или же \r

  • (?m) включает многострочный режим, который позволяет ^ соответствовать началу строки

  • однолинейный /DOTALL режим не установлен, потому что мы хотим .* остановиться в конце строки.

  • Я никогда не пользуюсь \s потому что он соответствует любому символу пробела, включая пробел, табуляцию, возврат каретки (\r) и перевод строки (\n). Если вы просто хотите найти совпадение, которое может занимать несколько строк, можно использовать \s или же . в однолинейном режиме. Но эта задача включает в себя сопоставление вещей в зависимости от их положения относительно начала строки. Это гораздо проще сделать, если вы явно сопоставите различные типы пробельных символов.

Если вы используете Python \h а также \R Shorthands не будет работать, поэтому вам нужно быть более многословным:

(?m)^[ \t]*\|.*(?:[\r\n]+[ \t]*\|.*)*

Обратите внимание, что [\r\n]+ также будет соответствовать пустым строкам; если вы хотите убедиться, что между строками находится ровно один разделитель строк, используйте вместо этого:

(?m)^[ \t]*\|.*(?:(?:\r\n|[\r\n])[ \t]*\|.*)*

Вы можете попробовать этот шаблон без модификатора s:

(?:(?:^|(?<=\n))[^\S\r\n]*\|.*(?:\r?\n|$)?)+

Для тех, кто использует Perl, вы можете использовать приведенный ниже код. Я уверен, что это может быть лучше. Я был бы рад узнать, если кто-то может помочь мне улучшить код

my $Str = "Lorem ipsum dolor sit amet,
consectetur adipisicing
elit,
|sed do
        |eiusmod tempor incididunt
     |ut labore et dolore magna aliqua.
Ut enim ad minim veniam,
quis nostrud exercitation
ullamco laboris nisi ut
aliquip ex ea commodo consequat.";
@lLine = split('\n', $Str);
foreach $lLine (@lLine) {
    if($lLine =~ /^[\s\|]+.*$/) {
        $ReturnStr .= $lLine;
    }
}

Выходные данные были следующими: "Sed do |eiusmod tempor incididunt" |ut labore et dolore magna aliqua.

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