python正则表达式:匹配几个正则表达式之一

时间:2017-09-04 14:27:50

标签: python regex

我有一个字符串和三个我想要匹配的模式,我使用python re包。具体来说,如果找到其中一个模式,则输出" Dislikes"否则,输出" Likes"。关于三种模式的简要信息:

  

模式1:检查字符串中的所有字符是否都是大写字母

     

模式2:检查连续字符是否相同,例如,   AABB ...

     

pattern3:检查模式XYXY是否存在,XY可以相同,   这种模式中的字母不需要彼此相邻。

当我单独编写模式时,程序按预期运行。但是当我使用交替|组合3个模式时,结果是错误的。我检查了stackoverflow帖子,例如herehere。解决方案提供给我不起作用。

以下是可以正常使用的原始代码:

import sys
import re

if __name__ == "__main__":
    pattern1 = re.compile(r"[^A-Z]+")
    pattern2 = re.compile(r"([A-Z])\1")
    pattern3 = re.compile(r"([A-Z])[A-Z]*([A-Z])[A-Z]*\1[A-Z]*\2")

    word = sys.stdin.readline()
    word = word.rstrip('\n')
    if pattern1.search(word) or pattern2.search(word) or pattern3.search(word):
        print("Dislikes")
    else:
        print("Likes")

如果我使用以下代码将3模式合并为1,则出现问题:

import sys
import re

if __name__ == "__main__":

    pattern = r"([A-Z])[A-Z]*([A-Z])[A-Z]*\1[A-Z]*\2|([A-Z])\1|[^A-Z]+"

    word = sys.stdin.readline()

    word = word.rstrip('\n')
    if re.search(word, pattern):
        print("Dislikes")
    else:
       print("Likes")

如果我们调用3种模式p1p2p3,我还尝试了以下组合:

pattern = r"(p1|p2|p3)"
pattern = r"(p1)|(p2)|(p3)"

但他们也没有按预期工作。合并它们的正确性是什么?

测试用例:

  • "喜欢":ABCABCDAABCBA
  • "不喜欢":ABBC(模式2),THETXH(模式3),ABACADA(模式3),AbCD(模式1)

1 个答案:

答案 0 :(得分:3)

这是一个加入你的模式:

([^A-Z]+|([A-Z])\2|([A-Z])[A-Z]*([A-Z])[A-Z]*\3[A-Z]*\4)

那么,为什么会这样呢?

它由简单的(p1|p2|p3)模式组成,其中p1p2p3是您之前定义的模式:

[^A-Z]+
([A-Z])\1
([A-Z])[A-Z]*([A-Z])[A-Z]*\1[A-Z]*\2

它可以分解为:

(
  [^A-Z]+
 |([A-Z])\2
 |([A-Z])[A-Z]*([A-Z])[A-Z]*\3[A-Z]*\
)

您遇到的问题是群组的编号。

首先,当您合并p2p3时,两者都会引用\1,但后者代表两种模式中的不同内容。 因此,p3应该变为...\2...\3,因为之前还有其他组。

此外,\number引用的组索引按打开顺序编制索引。 因此,对应于外部(...|...|...)的开头的第一个括号被计为第一组,\1将引用它。 当然,这不是你想要的。 但另外,这会给您一个错误,因为\1指的是尚未关闭的组,因此没有定义。

因此,指数应该换一,变为\2\3\4

这样的A|B正则表达式通常嵌套在括号中,但外部的正则表达式实际上可以被删除,并且索引向后移动一个:

[^A-Z]+|([A-Z])\1|([A-Z])[A-Z]*([A-Z])[A-Z]*\2[A-Z]*\3

以下是这种模式的小型演示:

import sys
import re

if __name__ == "__main__":
    pattern1 = re.compile(r"[^A-Z]+")
    pattern2 = re.compile(r"([A-Z])\1")
    pattern3 = re.compile(r"([A-Z])[A-Z]*([A-Z])[A-Z]*\1[A-Z]*\2")    
    pattern = re.compile(r"([^A-Z]+|([A-Z])\2|([A-Z])[A-Z]*([A-Z])[A-Z]*\3[A-Z]*\4)")

    while True:
        try:
            word = input("> ")
            print(pattern1.search(word))
            print(pattern2.search(word))
            print(pattern3.search(word))
            print(pattern.search(word))
        except Exception as error:
            print(error)

互动环节:

> ABC    # Matches no pattern
None
None
None
None

> ABCBA  # Matches no pattern
None
None
None
None

> ABBC   # Matches p2
None
<_sre.SRE_Match object; span=(1, 3), match='BB'> # p2 is matched
None
<_sre.SRE_Match object; span=(1, 3), match='BB'> # Jointure gives the same match

> ABACADA # Matches p3
None
None
<_sre.SRE_Match object; span=(0, 7), match='ABACADA'> # p3 is matched
<_sre.SRE_Match object; span=(0, 7), match='ABACADA'> # Jointure gives the same match