常规模式与#34; ^ ab | cd $"之间的区别是什么?和^(ab | cd)$?

时间:2015-02-07 10:56:39

标签: python regex

下面有正则表达式模式的区别是什么?

pattern1 = "^ab|cd$"
pattern2 = "^(ab|cd)$"
pattern3 = "^(ab)|(cd)$"

我尝试编写一个正则表达式来匹配罗马数字格式(0~3999)。 我写了一个模式如下:

pattern = "^M{1,3}|(CM|C?D|D?C{1,3})|(X?L|XC|L?X{1,3})|(I?V|IX|V?I{1,3})$"

这种模式符合" DIIII"或XIIII或类似这种模式的东西,但我期望大多数我匹配。

为什么会这样?

2 个答案:

答案 0 :(得分:6)

r"^ab|cd$"

在开始时匹配ab或在结尾处匹配cd。请注意,这与位于行的中间或末尾的ab不匹配。同样,这与开头或中间的cd不匹配。

r"^(ab|cd)$"

匹配仅包含abcd的整行。此外,字符串cdab由一个组捕获。

r"^(ab)|(cd)$"

与第一个相同,但它会将abcd捕获到两个不同的组中。

答案 1 :(得分:3)

^ab|cd$表示

  1. 字符串的开头,然后是ab
  2. cd后跟字符串结尾。
  3. ab 123匹配,因为粗体部分与 1 匹配, 123 cd 匹配,因为粗体部分与 2 匹配。也就是说,|符号具有最低优先级。

    .search一起使用,与s.startswith('ab') or s.endswith('cd')相同;虽然 如果您使用.match代替.search,则模式必须与字符串的开头匹配,因此您获得s.startswith('ab') or s == 'cd'

    ^(ab|cd)$表示

    • 字符串的开头,后跟abcd,后跟字符串结尾
    • ab|cd匹配的任何内容均可用作match.group(1)

    ^(ab)|(cd)$表示与第一个相同,但如果ab匹配,则match.group(1)可用{}},如果匹配cd,则匹配为match.group(2)部分以(...)提供。

    请注意,(?:...)在正则表达式中有2个用途 - 它们将原子分组为单个原子,并使匹配对象中的匹配文本可用。如果您只需要分组,则应使用|代替,因为生成子匹配字符串可能很昂贵。


    关于罗马数字正则表达式的问题,您在上层使用了^M{1,3}|(CM|C?D|D?C{1,3})|(X?L|XC|L?X{1,3})|(I?V|IX|V?I{1,3})$ 分支错误。

    .match

    如果与.search一起使用(M{1,3},则2-4甚至不绑定到字符串的开头),它代表

    1. 字符串的开头,后跟CM|C?D|D?C{1,3}以及
    2. 之后的任何内容
    3. 字符串的开头,后跟X?L|XC|L?X{1,3}以及
    4. 之后的任何内容
    5. 字符串的开头,后跟I?V|IX|V?I{1,3}以及
    6. 之后的任何内容
    7. 字符串的开头,后跟|,后跟字符串结尾。

    8. 您不希望在主要级别使用?,而是将这些1-4中的每一个都作为可选项,(?: );您也希望通常将非捕获组(^(?:M{1,3})?(?:CM|C?D|D?C{1,3})?(?:X?L|XC|L?X{1,3})?(?:I?V|IX|V?I{1,3})?$ )分组。因此我们得到:

      (?=...)

      除了它仍匹配空字符串。要使其与空字符串不匹配,可以使用零宽度正向预测来要求整个构造匹配至少1个(任意)字符。

      来自Python docs

        

      ...       匹配如果Isaac (?=Asimov)匹配下一个,但不消耗任何字符串。这称为先行断言。例如,'Isaac '只有在'Asimov'之后才匹配^

      因此我们可以在字符串开头^.之后放置它,以确保整个字符串至少匹配^(?=.)(?:M{1,3})?(?:CM|C?D|D?C{1,3})?(?:X?L|XC|L?X{1,3})?(?:I?V|IX|V?I{1,3})?$ (即字符串开头后跟1个字符):

      ^

      表示:

      • 字符串的开头((?=.)
      • 字符串结尾前至少有一个字符(M{1,3}
      • CM|C?D|D?C{1,3}(可选),然后是
      • X?L|XC|L?X{1,3}(可选),然后是
      • I?V|IX|V?I{1,3}(可选),然后是
      • $(可选),然后是
      • 字符串{{1}}
      • 的结尾

      应该是你想要的。