Python 正则表达式返回第一个和最后一个匹配项,而不是在匹配括号之间返回第一个和第二个匹配项
我正在尝试解析文本以提取所需的字符串。我在Python 正则表达式返回第一个和最后一个匹配项,而不是在匹配括号之间返回第一个和第二个匹配项,python,python-3.x,regex,python-2.7,Python,Python 3.x,Regex,Python 2.7,我正在尝试解析文本以提取所需的字符串。我在regex中遗漏了一些东西,有人能帮我找出问题所在吗 这是我的剧本: import re a = """ block1 #(/*AUTOINSTPARAM*/ // Parameters .THREE (3), // comment .TWO (2), // comment .ONE
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')
#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)
问题在于
*
尽可能多地匹配(贪婪),并且使用re.DOTALL
它将尽可能少地匹配整个字符串leavig,以保持匹配
基本上,任何带有*
的正则表达式(如果允许
真正捕获所有内容)将只匹配一次或根本不匹配,因为它能够匹配rexpression其余部分可能匹配的任何内容
仅使用*?
也无法解决此问题,因为:
字符串的另一个问题是括号。Regex(没有一些奇特的扩展)只能匹配具有有限嵌套的括号。假设autoinstpram
块中的最大嵌套深度为2,则以下正则表达式将起作用:
vvvvv blockX vvvvv instX
(\w+)\s*(#\([^(]*(\([^)]*\)[^()]*)*\))?[^\n]*\s*(\w+)\s*\(
^^inner^^
^^ outer bracket ^^
这些[^()]
组有一套
来防止它通过忽略它们来吃掉任何损坏的括号。如果您对格式了解更多,您可以进一步缩小范围
还请注意,此正则表达式假定最后一个
)
和instX
之间的注释匹配[^\n]*\s*
,并且它将接受括号内没有括号的任何内容。请尝试以下操作:
('except_check', 'data_check')
('abc', 'mask')
#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
选项(尽管解决此问题很简单)。如果第二组的单词字符在2个右括号之后,您可以省略re.DOTALL
,例如使用[\s\s]在多行上延伸的模式*?
尽可能少地匹配,直到遇到两个连续的括号
此模式基于示例数据,并且可能容易出错,因为它依赖于2个括号作为块2之前的最后一部分
^\s*(\w+)\r?\n\s*#\([\s\S]*?\)\s*\).*\r?\n\s*(\w+)
另一个选项是匹配第一个块后不以单词字符开头的行,并在组2中捕获以单词字符开头的行的单词字符
^\s*(\w+)\r?\n[^\S\r\n]*#\(.*(?:\r?\n(?![^\S\r\n]*\w).*)*\r?\n[^\S\r\n]+(\w+)
它对我不起作用,因为参数不是固定的,我需要在正则表达式中将所有参数作为可选参数。但是正则表达式完全忽略了这些参数。外括号部分将消耗
#(/*AUTO…
和之间的任何内容)//comment
。非常感谢!它非常有效!感谢您的反馈。很高兴知道它有效。@我正在尝试使用相同的正则表达式来进行此输入:除了检查(.a(m),.b(w),.c(x),.d(1) ,.e(1))数据检查(//输出,但无法获得所需的输出('除了检查','数据检查')。知道为什么吗?在我的环境中,它也可以工作。你能不能不在注释中发布输入,而是添加到你的问题中以保留换行符和缩进。然后我也会用它进行测试。谢谢你的更新。我已经根据你的输入修改了我的正则表达式。旧的一个保留注释,作为参考。如果你有新的提问,问一个新问题,或者如果你接受的答案不可接受,就拒绝接受。