[英]Reuse part of a Regex pattern
考虑这个(非常简化的)示例字符串:
1aw2,5cx7
如您所见,它是由逗号分隔的两位digit/letter/letter/digit
值。
现在,我可以将其与以下内容进行匹配:
>>> from re import match
>>> match("\d\w\w\d,\d\w\w\d", "1aw2,5cx7")
<_sre.SRE_Match object at 0x01749D40>
>>>
问题是,我必须写\\d\\w\\w\\d
两次。 对于小模式,这还不错,但是,对于更复杂的正则表达式,两次编写完全相同的内容会使最终模式变得庞大且难以处理。 这似乎也是多余的。
我尝试使用命名的捕获组:
>>> from re import match
>>> match("(?P<id>\d\w\w\d),(?P=id)", "1aw2,5cx7")
>>>
但它不起作用,因为它正在寻找1aw2
两次出现,而不是digit/letter/letter/digit
。
有没有办法保存模式的一部分,例如\\d\\w\\w\\d
,以便以后可以在同一模式中使用它? 换句话说,我可以在模式中重用子模式吗?
不,当使用标准库re
模块时,正则表达式模式不能被“符号化”。
你总是可以通过重用 Python 变量来做到这一点,当然:
digit_letter_letter_digit = r'\d\w\w\d'
然后使用字符串格式来构建更大的模式:
match(r"{0},{0}".format(digit_letter_letter_digit), inputtext)
或者,使用 Python 3.6+ f 字符串:
dlld = r'\d\w\w\d'
match(fr"{dlld},{dlld}", inputtext)
我经常使用这种技术从可重用的子模式中组合出更大、更复杂的模式。
如果你准备安装外部库,那么regex
项目可以通过一个regex子程序调用来解决这个问题。 语法(?<digit>)
重新使用已使用(隐式编号)捕获组的模式:
(\d\w\w\d),(?1)
^........^ ^..^
| \
| re-use pattern of capturing group 1
\
capturing group 1
您可以对命名捕获组执行相同操作,其中(?<groupname>...)
是命名组groupname
,并且(?&groupname)
、 (?P&groupname)
或(?P>groupname)
重新使用匹配的模式groupname
(后两种形式是与其他引擎兼容的替代形式)。
最后, regex
支持(?(DEFINE)...)
块来“定义”子例程模式,而无需它们在该阶段实际匹配任何内容。 您可以在该构造中放置多个(..)
和(?<name>...)
捕获组,以便稍后在实际模式中引用它们:
(?(DEFINE)(?<dlld>\d\w\w\d))(?&dlld),(?&dlld)
^...............^ ^......^ ^......^
| \ /
creates 'dlld' pattern uses 'dlld' pattern twice
明确地说:标准库re
模块不支持子程序模式。
注意:这将适用于PyPi regex module ,而不适用于re
模块。
在您的情况下,您可以使用符号(?group-number)
:
(\d\w\w\d),(?1)
它相当于:
(\d\w\w\d),(\d\w\w\d)
请注意, \\w
包括\\d
。 正则表达式将是:
(\d[a-zA-Z]{2}\d),(?1)
我被同样的问题困扰并写了这个片段
import nre
my_regex=nre.from_string('''
a=\d\w\w\d
b={{a}},{{a}}
c=?P<id>{{a}}),(?P=id)
''')
my_regex["b"].match("1aw2,5cx7")
由于缺乏更具描述性的名称,我将部分正则表达式命名为a
、 b
和c
。
访问它们就像{{a}}
一样简单
import re
digit_letter_letter_digit = re.compile("\d\w\w\d") # we compile pattern so that we can reuse it later
all_finds = re.findall(digit_letter_letter_digit, "1aw2,5cx7") # finditer instead of findall
for value in all_finds:
print(re.match(digit_letter_letter_digit, value))
既然你已经在使用 re,为什么不使用字符串处理来管理模式重复:
pattern = "P,P".replace("P",r"\d\w\w\d")
re.match(pattern, "1aw2,5cx7")
或者
P = r"\d\w\w\d"
re.match(f"{P},{P}", "1aw2,5cx7")
尝试使用反向引用,我相信它可以像下面这样匹配
1aw2,5cx7
你可以用
(\d\w\w\d),\1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.