考虑这个(非常简化的)示例字符串:
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
,因此可以在同一模式中使用后者?换句话说,我可以在模式中重用子模式吗?
答案 0 :(得分:12)
不,使用标准库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-strings:
dlld = r'\d\w\w\d'
match(fr"{dlld},{dlld}", inputtext)
我经常使用这种技术从可重复使用的子模式中组合更大,更复杂的模式。
如果您准备安装外部库,regex
project可以使用regex subroutine call解决此问题。语法(?<digit>)
重用已使用(隐式编号)捕获组的模式:
(\d\w\w\d),(?1)
^........^ ^..^
| \
| re-use pattern of capturing group 1
\
capturing group 1
您可以对命名捕获组执行相同操作,其中(?<groupname>...)
是指定的组groupname
,(?&groupname)
,(?P&groupname)
或{ {1}}重复使用(?P>groupname)
匹配的模式(后两种形式是与其他引擎兼容的替代方案)。
最后,groupname
支持regex
块来“定义”子例程模式,而不会在该阶段实际匹配任何内容。您可以在该构造中放置多个(?(DEFINE)...)
和(..)
捕获组,然后在实际模式中引用它们:
(?<name>...)
要明确:标准库(?(DEFINE)(?<dlld>\d\w\w\d))(?&dlld),(?&dlld)
^...............^ ^......^ ^......^
| \ /
creates 'dlld' pattern uses 'dlld' pattern twice
模块不支持子例程模式。
答案 1 :(得分:5)
注意:这适用于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)
答案 2 :(得分:0)
我对同样的问题感到困扰并写了this snippet
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}}
答案 3 :(得分:0)
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))
答案 4 :(得分:0)
既然您已经在使用re,为什么不也使用字符串处理来管理模式重复:
pattern = "P,P".replace("P",r"\d\w\w\d")
re.match(pattern, "1aw2,5cx7")
OR
P = r"\d\w\w\d"
re.match(f"{P},{P}", "1aw2,5cx7")
答案 5 :(得分:-1)
尝试使用反向引用,我相信它的工作原理如下,以匹配
1aw2,5cx7
您可以使用
(\d\w\w\d),\1