我正在使用https://github.com/mrabarnett/mrab-regex(通过pip install regex
,但此处出现故障:
pattern_string = r'''
(?&N)
^ W*? ENTRY W* (?P<entries> (?&Range) ) (?&N)
(?(DEFINE)
(?P<Decimal>
[ ]*? d+ (?:[.,] d+)? [ ]*?
)
(?P<Range>
(?&Decimal) - (?&Decimal) | (?&Decimal)
#(?&d) (?: - (?&d))?
)
(?P<N>
[sS]*?
)
)
'''
flags = regex.MULTILINE | regex.VERBOSE #| regex.DOTALL | regex.V1 #| regex.IGNORECASE | regex.UNICODE
pattern = regex.compile(pattern_string, flags=flags)
bk2 = f'''
ENTRY: 0.0975 - 0.101
'''.strip()
match = pattern.match('ENTRY: 0.0975 - 0.101')
match.groupdict()
给出:
{'entries': '0.0975', 'Decimal': None, 'Range': None, 'N': None}
它错过了第二个值。
> pip show regex
Name: regex
Version: 2022.1.18
Summary: Alternative regular expression module, to replace re.
Home-page: https://github.com/mrabarnett/mrab-regex
Author: Matthew Barnett
Author-email: regex@mrabarnett.plus.com
License: Apache Software License
Location: ...
Requires:
Required-by:
> python --version
Python 3.10.0
问题是,您在Decimal
组模式中定义的空间被消耗掉了,而DEFINE
模式是原子的,所以尽管最后一个[ ]*?
部分是惰性的,可以匹配零次,但一旦匹配,就没有回头路了。如果将Decimal
模式放入一个原子组中并比较两个模式,则可以检查此项。(?mx)^W*?ENTRYW*(?P<entries>(?>[ ]*? d+ (?:[.,] d+)? [ ]*?) - (?>[ ]*? d+ (?:[.,] d+)? [ ]*?) | (?>[ ]*? d+ (?:[.,] d+)? [ ]*?))
使用DEFINE
块公开与正则表达式相同的行为,而(?mx)^W*?ENTRYW*(?P<entries>[ ]*? d+ (?:[.,] d+)? [ ]*? - [ ]*? d+ (?:[.,] d+)? [ ]*? | [ ]*? d+ (?:[.,] d+)? [ ]*?)
正确地找到匹配项。
最简单的解决方法是将可选的空间模式移动到Range
组模式中。
你可能想在这里介绍其他一些小的增强功能:
- 由于您只对捕获的子字符串感兴趣,因此不需要将
regex.match
与N
组模式([sS]*?
(一起使用,您可以使用regex.search
并从正则表达式中删除N
模式 - 您不需要为类似
a|a-b
的模式使用组,您可以使用更高效的可选非捕获组方法a(?:-b)?
因此,正则表达式可以看起来像
^ W* ENTRY W* (?P<entries> (?&Range) )
(?(DEFINE)
(?P<Decimal>
d+ (?:[.,] d+)?
)
(?P<Range>
(?&Decimal)(?: *- *(?&Decimal))*
)
)
请参阅regex演示。
请参阅Python演示:
import regex
pattern_string = r'''
^ W* ENTRY W* (?P<entries> (?&Range) )
(?(DEFINE)
(?P<Decimal>
d+ (?:[.,] d+)?
)
(?P<Range>
(?&Decimal)(?: *- *(?&Decimal))?
)
)
'''
flags = regex.MULTILINE | regex.VERBOSE
pattern = regex.compile(pattern_string, flags=flags)
bk2 = f'''
ENTRY: 0.0975 - 0.101
'''.strip()
match = pattern.search('ENTRY: 0.0975 - 0.101')
print(match.groupdict())
输出:
{'entries': '0.0975 - 0.101', 'Decimal': None, 'Range': None}