Python正则表达式检测字符串后面的多个可选子字符串之一?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (555)

我需要匹配以下模式: AAXX#

其中: * AA来自list1-3个字母alpha前缀的集合(即a ), * 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

和ditto item = hclr5item = hclx9但不是hcleaner9

提问于
用户回答回答于

我的方法是

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

对于您想要的布尔输出,您可以简单地将匹配对象强制转换为'bool'。

用户回答回答于

代码中的一些误解包括字符类的使用(语法:) [ ... ]。当您使用字符类,从字符类中的任何单个字符将尝试匹配字符串(有例外,一些其他字符时,这些字符是^-当放置在特定位置)。这意味着:

[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')结果(或者('', '', '')如果它不匹配)

至于正则表达式本身,你可以在这里测试它(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获得额外的性能)

扫码关注云+社区

领取腾讯云代金券