下面有正则表达式模式的区别是什么?
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或类似这种模式的东西,但我期望大多数我匹配。
为什么会这样?
答案 0 :(得分:6)
r"^ab|cd$"
在开始时匹配ab
或在结尾处匹配cd
。请注意,这与位于行的中间或末尾的ab
不匹配。同样,这与开头或中间的cd
不匹配。
r"^(ab|cd)$"
匹配仅包含ab
或cd
的整行。此外,字符串cd
或ab
由一个组捕获。
r"^(ab)|(cd)$"
与第一个相同,但它会将ab
或cd
捕获到两个不同的组中。
答案 1 :(得分:3)
^ab|cd$
表示
ab
或 cd
后跟字符串结尾。即 ab
123
匹配,因为粗体部分与 1 匹配,
123
cd
匹配,因为粗体部分与 2 匹配。也就是说,|
符号具有最低优先级。
与.search
一起使用,与s.startswith('ab') or s.endswith('cd')
相同;虽然
如果您使用.match
代替.search
,则模式必须与在字符串的开头匹配,因此您获得s.startswith('ab') or s == 'cd'
。
^(ab|cd)$
表示
ab
或cd
,后跟字符串结尾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甚至不绑定到字符串的开头),它代表
CM|C?D|D?C{1,3}
以及或 X?L|XC|L?X{1,3}
以及或 I?V|IX|V?I{1,3}
以及或 |
,后跟字符串结尾。您不希望在主要级别使用?
,而是将这些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}
(可选),然后是$
(可选),然后是应该是你想要的。