【问题标题】:regex returns first and last match instead of returning first and second match inbetween matching parenthesis正则表达式返回第一个和最后一个匹配,而不是在匹配括号之间返回第一个和第二个匹配
【发布时间】:2021-06-17 09:37:59
【问题描述】:

我正在尝试解析文本以提取所需的字符串。我在regex 中遗漏了一些东西,有人可以帮我找出这里的问题吗?

这是我的脚本:

import re
a = """
    block1
          #(/*AUTOINSTPARAM*/
        // Parameters
        .THREE          (3),     // comment
        .TWO            (2), // comment
        .ONE    (1))             // comment
        inst1
           (/*AUTOINST*/
        // extra
        // output

    block2
          #(/*AUTOINSTPARAM*/
        // Parameters
        .THREE          (3),     // comment
        .TWO            (2), // comment
        .ONE    (1))             // comment
        inst2
           (/*AUTOINST*/
        // extra
        // output
"""

op = re.findall(r'(\w+)\s*(#\(.*\))?.*?(\w+)\s*\(', a, re.MULTILINE|re.DOTALL)
for i in op:
    print(i[0],i[2])

这是输出:

('block1', 'inst2')

预期输出:

('block1', 'inst1')
('block2', 'inst2')

更新: 尝试测试与接受的答案相同的正则表达式的以下输入:

import re
a = """
    except_check
          #(
            .a        (m),
            .b        (w),
            .c        (x),
            .d        (1),
            .e        (1)
        )
        data_check
           (// Outputs

  abc
  #(
    .a                          (b::c)
   )
   mask
   (/*AUTOINST*/

"""

op = re.findall(r'^\s*(\w+)\s*$\n(?:^\s*[#/.].*$\n)*^\s*(\w+)\s*\(', a, re.MULTILINE)
for i in op:
    print(i)

它没有返回任何东西。它应该返回以下内容:

('except_check', 'data_check')
('abc', 'mask')

【问题讨论】:

  • 如果您有新问题,请提出新问题,或者如果您接受的答案不可接受,则不接受。

标签: python python-3.x regex python-2.7


【解决方案1】:

请您尝试以下方法:

#op = re.findall(r'^\s*(\w+)\s*$\n(?:^\s*[#/.].*$\n)*^\s*(\w+)\s*\(', a, re.MULTILINE)
op = re.findall(r'^\s*(\w+)\s*$\n(?:^\s*[^\w\s].*$\n)*^\s*(\w+)\s*\(', a, re.MULTILINE)
for i in op:
    print(i)

输出:

('block1', 'inst1')
('block2', 'inst2')
  • ^\s*(\w+)\s*$\n 匹配块名行
  • (?:^\s*[^\w\s].*$\n)* 匹配参数行
  • ^\s*(\w+)\s*\( 匹配实例名称行

请注意,我已禁用 re.DOTALL 选项(尽管解决此问题很简单)。

【讨论】:

  • 非常感谢!它就像一个魅力!
  • 感谢您的反馈。很高兴知道它有效。
  • @stackoverflow.com/users/8572380/tshiono 我正在尝试对此输入使用相同的正则表达式:except_check #( .a (m), .b (w), .c (x), .d (1) , .e (1) ) data_check (// 输出但无法获得所需的输出 ('except_check', 'data_check')。知道为什么吗?
  • 在我的环境中它也可以正常工作。您可以不在评论中发布输入,而是添加到您的问题以保留换行符和缩进。然后我也会用它来测试。
  • 感谢您的更新。我已经根据您的输入修改了我的正则表达式。旧的被注释掉,仅供参考。
【解决方案2】:

问题是.* 尽可能匹配(贪婪),而re.DOTALL 它将尽可能少地匹配整个字符串 leavig 以仍然匹配 /em>。

(\w+)\s*(#\(.*\))?.*?(\w+)\s*\(
            ^^ this one

基本上任何带有.* 的正则表达式(如果允许. 真正捕获所有内容)只会匹配一次或根本不匹配,因为它能够匹配r 表达式的其余部分也可以匹配的任何内容。

仅使用.*? 也无法解决此问题,因为:

字符串的另一个问题是括号。正则表达式(没有一些花哨的扩展)只能匹配有限嵌套的括号。假设 AUTOINSTPARAM 块中的最大嵌套深度为 2,则以下正则表达式将起作用:

vvvvv blockX                                    vvvvv instX
(\w+)\s*(#\([^(]*(\([^)]*\)[^()]*)*\))?[^\n]*\s*(\w+)\s*\(
                  ^^inner^^
          ^^ outer bracket         ^^  

这些[^()] 组位于. 的位置,以防止它通过忽略它们而吃掉任何损坏的括号。如果您对格式有更多了解,则可以进一步缩小范围。

另请注意,此正则表达式假定最后一个 )instX 之间的注释与 [^\n]*\s* 匹配,并且它将接受括号内不是括号的任何内容。

【讨论】:

  • 它对我不起作用,因为参数不固定,我需要在正则表达式中将所有参数作为可选参数。
  • 但是参数被正则表达式完全忽略。外括号部分将消耗#(/*AUTO...) //comment 之间的任何内容。
【解决方案3】:

如果第二组的单词字符在 2 个右括号之后,您可以省略 re.DOTALL 并使用例如使用 [\s\S]*? 匹配的跨越多行的模式,直到遇到 2 个连续的括号.

此模式基于示例数据,可能容易出错,因为它依赖于 2 括号作为块 2 之前的最后一部分。

^\s*(\w+)\r?\n\s*#\([\s\S]*?\)\s*\).*\r?\n\s*(\w+)

Regex demo

另一个选项可能是匹配第一个块之后不以单词字符开头的行,并在第 2 组中捕获该行的单词字符。

^\s*(\w+)\r?\n[^\S\r\n]*#\(.*(?:\r?\n(?![^\S\r\n]*\w).*)*\r?\n[^\S\r\n]+(\w+)

Regex demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    • 2019-10-02
    • 1970-01-01
    • 2014-08-12
    相关资源
    最近更新 更多