如何在Python中编写正则表达式来查找字符组合,但每个字符只能出现一次

2024-09-30 10:27:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我想知道字符串中的“xy”是否是可选的,对于每个字符它只能出现一次。例如:

def findpat(texts, pat):
    for text in texts:
        if re.search(pat, t):
            print re.search(pat, t).group()
        else:
            print None    

pat = re.compile(r'[xy]*?b')
text = ['xyb', 'xb', 'yb', 'yxb','b', 'xyxb']
findpat(text, pat)

# it prints
# xyb
# xb
# yb
# yxb
# b
# xyxb

对于最后一个,我想要的输出是“yxb”。 我应该如何修改我的正则表达式?非常感谢


Tags: 字符串textresearch字符printxypat
3条回答

你可以用这个模式

r'(x?y?|yx)b'

要分解,有趣的部分x?y?|yx将匹配:

  1. 空字符串
  2. 只有x
  3. 只有y
  4. xy公司
  5. 在另一个分支,yx

作为一个建议,当您对regex不太满意并且场景数量很少时,您可以简单地强制模式。这很难看,但它清楚地表明了你的情况:

^{pr2}$

第2部分。

对于一个通用的解决方案,它也会这样做,但是对于任意数量的字符,而不仅仅是{x,y},可以使用以下regex样式:

r'(?=[^x]*x?[^x]*b)(?=[^y]*y?[^y]*b)(?=[^z]*z?[^z]*b)[xyz]*b'

我来解释一下:

  • 通过使用lookaheads,您可以向前移动regex光标,对于每个位置,您只需“向前看”,看看下面的内容是否符合特定条件。通过使用此技术,您可以将多个条件组合到一个正则表达式中。在
  • 对于光标位置,我们测试集合中的每个字符,使其从该位置最多出现一次,直到我们匹配目标b字符。我们用这个模式[^x]*x?[^x]*,这意味着匹配not-x如果有,最多匹配一个x,然后匹配任意数量的not x
  • 一旦满足了测试条件,我们就开始移动光标并匹配所需集合中的所有字符,直到找到ab。在这一点上,我们保证不会匹配任何重复项,因为我们执行了前瞻性测试。在

注意:我强烈怀疑它的性能很差,因为它有回溯功能。你应该只对小的测试字符串使用它。在

Test it.

嗯,真正通过测试用例的regexp是:

 pat = re.compile(r'(x|y|xy|yx)?b$')

其中“$”将字符串锚定在末尾,从而确保它是最后找到的匹配项。在

然而,使用regexp机制来确保只使用集合中的一个匹配字符会有点棘手。。。在

您可以使用以下方法:匹配并捕获两个组,([xy]*)(b)。然后,一旦找到匹配项,检查组1中的值的长度是否与该值中的唯一字符数相同。如果不是,请从组值的开头删除字符,直到获得长度为唯一字符数的字符串。在

比如:

def findpat(texts, pat):
    for t in texts:
        m = re.search(pat, t)                   # Find a match
        if m:
            tmp = set([x for x in m.group(1)])  # Get the unqiue chars
            if len(tmp) == len(m.group(1)):     # If Group 1 length is the same
                print re.search(pat, t).group() # Report a whole match value
            else:
                res = m.group(1)
                while len(tmp) < len(res):      # While the length of the string is not
                    res = res[1:]               # equal to the number of unique chars, truncate from the left
                print "{}{}".format(res, m.group(2)) # Print the result
        else:
            print None               # Else, no match

pat = re.compile(r'([xy]*)(b)')
text = ['xyb', 'xb', 'yb', 'yxb','b', 'xyxb']
findpat(text, pat)
# => [xyb, xb, yb, yxb, b, yxb]

参见Python demo

相关问题 更多 >

    热门问题