我需要匹配以下模式:AAXX#
位置:
* AA
来自1-3个char字母前缀的集合(即list
),
* XX
来自不同的预定义字符串列表,并且
* any single-digit numeral
之后。
AA字符串:['bo','h','fr','sam','pe']
XX个字符串:cl
+ ['x','n','r','nr','eaner]
//否则,// ro
所需结果:bool指示是否有任何可能的连击与提供的字符串匹配。
示例测试字符串:
item = "boro1"
-即bo
+ ro
+ 1
item = "samcl2"
-即sam
+ cl
+ 2
item = "hcln3"
-即h
+ cln
+ 3
我能想到的最好的方法是使用一个循环,但是我在使用必需的正则表达式时遇到了麻烦。它适用于单字母可选cln, clx, clr
,但不适用于较长字母的clnr, cleaner
。
item = "hclnr2" #h + clnr + 2
out = False
arr = ['bo','h','fr','sam','pe']
for mnrl in arr:
myrx = re.escape(mnrl) + r'cl[x|n|r|nr|eaner]\d'
thisone = bool(re.search(myrx, item))
print('mnrl: '+mnrl+' - ', thisone)
if thisone: out = True
##########################################################################
# SKIP THIS - INCLUDED IN CASE S/O HAS A BETTER SOLUTION THAN A SECOND LOOP
# THE ABOVE FOR-LOOP handled THE CL[opts] TESTS, THIS LOOP DOES THE RO TESTS
##########################################################################
#if not out: #If not found a match amongst the "cl__" options, test for "ro"
# for mnrl in arr:
# myrx = re.escape(mnrl) + r'ro\d'
# thisone = bool(re.search(myrx, item))
# print('mnrl: '+mnrl+' - ', thisone)
# if thisone: out = True
##########################################################################
print('result: ', out)
mnrl: bo - False
mnrl: h - False <======
mnrl: fr - False
mnrl: sam - False
mnrl: pe - False
item
更改为:item = "hcln2" #h + cln + 2
打印:
mnrl: bo - False
mnrl: h - True <========
mnrl: fr - False
mnrl: sam - False
mnrl: pe - False
item = hclr5
或item = hclx9
的同上,但不是hcleaner9
答案 0 :(得分:2)
我的方法是
import re
words = ['boro1', 'samcl2', 'hcln3', 'boro1+unwantedstuff']
p = r'(bo|h|fr|sam|pe)(cl(x|n|r|nr|eaner|)|ro)\d$'
for w in words:
print(re.match(p, w))
结果:
<_sre.SRE_Match object; span=(0, 5), match='boro1'>
<_sre.SRE_Match object; span=(0, 6), match='samcl2'>
<_sre.SRE_Match object; span=(0, 5), match='hcln3'>
None
对于所需的布尔输出,您只需将match对象转换为'bool'。
答案 1 :(得分:2)
您的代码中有些误解包括字符类的使用(语法:[ ... ]
)。当您使用字符类时,字符类中的任何单个字符都将尝试匹配字符串(使用其他一些字符的情况除外,这些字符在特定位置时分别为^
和-
职位)。这意味着:
[x|n|r|nr|eaner]
将匹配x,|,n,r,e,a中的任何一个字符(重复的字符实际上将被丢弃)
我不确定您为什么要在代码中执行诸如re.escape
之类的所有复杂操作,我相信您可以理解以下代码片段以使其适应您的情况:
import re
def matchPattern(item, extract=False):
result = re.match(r"(bo|h|fr|sam|pe)((?:cl(?:nr|eaner|[xnr]|))|ro)([0-9])$", item)
if result:
if extract:
return (result.group(1), result.group(2), result.group(3))
else:
return True
else:
if extract:
return ('','','')
else:
return False
我对def
进行了一些微调,以便在调用matchPattern("boro1")
时得到布尔值;如果要获取子字符串成分,则可以调用matchPattern("boro1", True)
,然后将得到('bo', 'ro', '1')
作为结果(如果不匹配,则返回('', '', '')
)
关于正则表达式本身,您可以在here(regex101.com)上对其进行测试
如果要使用|
正则表达式运算符,则需要使用组。在我上面使用的正则表达式中,
(bo|h|fr|sam|pe)
表示bo,h,fr,sam或pe之一((?:cl(?:nr|eaner|[xnr]|))|ro)
的意思是(?:cl(?:nr|eaner|[xnr]|))
(这意味着cl后跟nr,eaner,x,n,r或什么都不是)或ro ([0-9])
代表一个数字(我希望此数字比\d
更重要)