Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 正则表达式:向后匹配最接近的值_Python_Regex - Fatal编程技术网

Python 正则表达式:向后匹配最接近的值

Python 正则表达式:向后匹配最接近的值,python,regex,Python,Regex,是否有方法匹配包含特定值的所有节名,如下所示: section aaa: some values value 5 section bbb: more values value 6 section ccc: some values value 5 section ddd: more values value 6 例如: section (.*?):.*?value 6 (DOTALL|MULTILINE) 将匹配aaa,ccc,而不是bbb,d

是否有方法匹配包含特定值的所有节名,如下所示:

section aaa:
   some values
   value 5
section bbb:
   more values
   value 6
section ccc:
   some values
   value 5
section ddd:
   more values
   value 6
例如:

section (.*?):.*?value 6  (DOTALL|MULTILINE)
将匹配
aaa
ccc
,而不是
bbb
ddd

有没有办法匹配
bbb
ddd

谢谢

更新: 有一些解决方案(有效)基于以下假设:值行不包含冒号或不以空格开头。但是,是否有方法匹配
值6
并获取其前面最近的部分,即即使值包含冒号或未缩进

NHAHDH的答案是:你不能用正则表达式向后搜索。有lookbehind(在本例中,它需要可变宽度lookbehind),但效率极低,Python默认re模块不支持任何形式的lookbehind

我的结论是: 这可以使用具有上述假设的纯正则表达式来实现,或者(我更喜欢)使用drewk建议的组合正则表达式python方法(该方法也有一些假设,即该部分必须包含

更新2: 这就是我的结局。它似乎不受上述限制。它确实假设值不能有以
节开始的行。*:
。我们将节与下一节进行匹配,但不包括它(通过使用
(?=…)
语法),为了匹配最后一节,我们有
\Z
,它是字符串的结尾

for m in re.finditer(r'^section (.*?):(.*?)(?=(^section .*:)|\Z)', str1, re.MULTILINE | re.DOTALL):
    section = m.group(1)
    values = m.group(2)    
    if "value 6" in values:
        print section

如果您只需要最后一部分:

print re.findall(r'^section (\w+):',tgt,flags=re.MULTILINE)[-1]
通过您的编辑,可以完成以下操作:

import re

tgt='''\
section aaa:
   some values
   value 5
section bbb:
   more values
   value 6
section ccc:
   some values
   value 5
section ddd:
   more values
   value 6'''

pat=re.compile(r'^section (\w+):.*?value (\d+)',flags=re.MULTILINE|re.DOTALL)

print [(m.group(1),m.start(),m.end()) 
          for m in pat.finditer(tgt)
          if m.group(2)=='6']
印刷品:

[('bbb', 39, 77), ('ddd', 117, 155)]
编辑

看,没有冒号或缩进:

进口稀土

tgt='''\
section aaa:
   some values
   value 5
section bbb
   more values
value 6
section ccc:
   some values
   value 5
section ddd:
   more values
   value 6'''

pat=re.compile(r'^section (\w+).*?^\s*value (\d+)',flags=re.MULTILINE|re.DOTALL)

print [(m.group(1),m.start(),m.end()) 
          for m in pat.finditer(tgt)
          if m.group(2)=='6']
相同输出

编辑2

如果筛选出可能没有匹配“value”部分的部分很重要,请使用两个正则表达式,第一个正则表达式具有前瞻性:

import re

tgt='''\
section aaa:
   some values

section bbb:
   more values
   value 6
section ccc:
   some values
   value 5
section ddd:
   more values
   value 6'''

pat1=re.compile(r'^section (\w+):(.*?)(?=section|\Z)',flags=re.MULTILINE|re.DOTALL)
pat2=re.compile(r'^\s*value (\d+)',flags=re.MULTILINE)

for m in pat1.finditer(tgt):
    m2=re.search(r'^\s*value (\d+)',m.group(2),flags=re.MULTILINE)
    if m2 and m2.group(1)=='6':
        print m.group(1)
打印
bbb
ddd

section ([^:]+):[^:]+value 6  (DOTALL|MULTILINE)

当然,只有在“更多值”部分没有冒号的情况下,这才有效。假定节名不包含任何
,并且必须在行的开头声明一个有效的节,此解决方案将查找具有给定值的节的所有名称。必须使用
多行
选项编译正则表达式

^section ([^:\n]+):.*\n( +.*\n)*( +value 6\b)
说明:

  • ^section([^:\n]+):..*\n
    搜索行以
    section
    开始,后跟节名(假定不包含
    或新行字符),然后是
    。其余的
    *\n
    部分的其余部分
    行匹配
  • (++.*\n)*
    匹配至少有1个缩进空间的行。它确保我们不会“溢出”到下一节
  • (+value 6\b)
    匹配包含所需值的行(部分)<代码>\b确保
    6
    后面没有其他数字(63)、字母字符(6a)或下划线(6)
即使
某些值
包含冒号
,此解决方案仍然有效


请注意,如果使用
LOCALE
标志或
UNICODE
标志,则
\b
的效果可能会有所不同。

为什么要匹配
aaa
ccc
?让我们围绕第二个
*?
创建第二个组,并查看它的输出:

>>> re.findall(r'section (.*?):(.*?)value 6',text, re.M | re.S)
[('aaa', '\n   some values\n   value 5\nsection bbb:\n   more values\n   '), ('ccc', '\n   some values\n   value 5\nsection ddd:\n   more values\n   ')]
从这一点我们可以看出,第二组捕获了比它应该捕获的更多的内容

为了避免这种情况,请确保第二个非贪婪消费者中的每个
后面都没有
^section
,以便在搜索
值6
时不会绕过新节的开头,而第一个消费者不会消费

>>> re.findall(r'section ([^:]*?):(?:.(?!^section))*?value 6',text, re.M | re.S)
['bbb', 'ddd']

你为什么不把它解析成一个字典呢?匹配实际上是替换的一部分-我想从一个大文件中删除包含某个值的所有部分。它确实有效!它基于显式描述节内容格式的技巧(在本例中,从空格开始)。然而,问题是,有没有可能做到逻辑上似乎很容易做到的事情:找到“值6”并向后搜索第一个匹配部分:@Ivan:你不能用正则表达式向后搜索。有look-behind(在本例中,它需要可变宽度的look-behind),但效率极低,Python default
re
模块不支持任何形式的look-behind。@Jerry问题已编辑,示例不同。它仍然与初始示例不匹配。只添加了两个部分,一个包含
值6
。它确实有效!它基于显式描述节内容格式的技巧(在本例中,值行不包含冒号)。然而,问题是,是否有可能做到逻辑上看起来很简单的事情:找到“值6”并向后搜索第一个匹配部分:谢谢,看起来将python逻辑与正则表达式相结合是最干净的。在这种情况下,纯正则表达式可以工作,但会变得复杂,并且有一定的假设(该节的内容具有一定的格式)如果某些节未包含
,则将获取以下节中的第一个值,如果恰好等于
6
,则尽管当前节未包含值参数,但仍将输出该节。例如,使用输入的
''\section aaa:some values section bbb:more values section ccc尝试此代码:有些值为6'
。输出为
[('aaa',0,94)]
,尽管
aaa
没有
参数。@ovgolovin:是的,这是这里的假设(限制)。