考虑以下(非常简化的)示例字符串:
1aw2,5cx7
如您所见,它是两个digit/letter/letter/digit值,以逗号分隔。
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两次。对于小模式,这并不是很糟糕,但是对于更复杂的正则表达式,两次编写完全相同的东西会使结束模式变得庞大而繁琐。这似乎也是多余的。
\d\w\w\d
我尝试使用命名捕获组:
>>> from re import match >>> match("(?P<id>\d\w\w\d),(?P=id)", "1aw2,5cx7") >>>
但这没用,因为它寻找的是两次1aw2,而不是digit/letter/letter/digit。
1aw2
有什么方法可以保存模式的一部分,例如\d\w\w\d,以便以后可以在同一模式中使用?换句话说,我可以在模式中重用子模式吗?
不可以,当使用标准库re模块时,正则表达式 模式 不能被“符号化”。
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>)重新使用了已使用(隐式编号)捕获组的模式:
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(后两种形式是与其他引擎兼容的替代品)。
(?<groupname>...)
groupname
(?&groupname)
(?P&groupname)
(?P>groupname)
最后,regex支持该(?(DEFINE)...)块以“定义”子例程模式,而无需在该阶段实际匹配任何子例程。你可以把多个(..)和(?<name>...)捕获组在结构,以后来指他们在实际的模式:
(?(DEFINE)...)
(..)
(?<name>...)
(?(DEFINE)(?<dlld>\d\w\w\d))(?&dlld),(?&dlld) ^...............^ ^......^ ^......^ | \ / creates 'dlld' pattern uses 'dlld' pattern twice
明确地说:标准库re模块不支持子例程模式。