【问题标题】:Matching *consecutive* lines that begin with an arbitrary amount of whitespace followed by a character匹配以任意数量的空格开头后跟一个字符的*连续*行
【发布时间】:2014-03-06 22:06:23
【问题描述】:

我正在尝试匹配连续行,这些行以任意数量的空格开头,后跟字符|。我正在使用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.

想要三个匹配,每行包含|

【问题讨论】:

    标签: regex recursive-regex


    【解决方案1】:

    如果您使用的是 PHP,应该这样做:

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

    一些兴趣点:

    • \h 匹配水平空格,表示空格和制表符

    • \R 匹配行分隔符,无论是\n\r\n 还是\r

    • (?m) 开启多行模式,允许^ 匹配行首

    • 单行/DOTALL 模式设置,因为我们希望.* 停止在行尾。

    • 我从不使用 \s,因为它匹配 任何 空白字符,包括空格、制表符、回车符 (\r) 和换行符 (\n)。如果您只想找到可能跨越多行的匹配项,可以在单行模式下使用\s.。但是这个任务涉及根据它们相对于行首的位置来匹配事物。如果您明确匹配不同类型的空白字符,这将更容易做到。

    如果您使用 Python,\h\R 速记将不起作用,因此您必须更加详细:

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

    注意[\r\n]+ 也会匹配空行;如果您想确保行之间只有一个行分隔符,请改用:

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

    【讨论】:

      【解决方案2】:

      你可以试试这个不带 s 修饰符的模式:

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

      【讨论】:

      • @DudeOnRock:此模式仅匹配以数量不足的空格开头后跟管道的连续行。由于点(默认情况下)与换行符不匹配,因此您无法在整个匹配中获得几行不以空格和管道开头的行。 \n\s*[^\|] 不起作用,因为它是错误的模式,仅此而已。我不能告诉你它错误的原因,因为这种模式对我来说毫无意义(我无法说出你想用它做什么)
      • @DudeOnRock:您可以通过添加您正在使用的语言来帮助您获得更相关的答案。
      • @DudeOnRock:为您感到高兴,请发布您的解决方案作为您自己问题的答案(面向未来的读者)。
      【解决方案3】:

      我自己解决了。我想我必须从我要排除的字符组中排除空格:

      n\s*[^\|\s]
      

      不太清楚为什么会这样,我偶然发现了这个。如果有人能解释这背后的原因,我将不胜感激。

      现在的完整表达如下:

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

      【讨论】:

        【解决方案4】:

        对于那些使用 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 laboure et dolore magna aliqua。

        【讨论】:

          猜你喜欢
          • 2023-02-09
          • 1970-01-01
          • 2016-05-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-15
          相关资源
          最近更新 更多