匹配交替的数字和字符
我看过谷歌的Python正则表达式教程,想测试一下我需要的一个模式。
- 字符串必须是10个字符长。
- 第1、3、5、7和9个字符必须是数字(1到5),而且不能重复。
- 其他字符可以是字母(a、b或c),这些字母可以重复。
举个例子:
1a2b4a3c5b # is valid
1a5c4b4a3b # is not valid because of two 4s
到目前为止,我尝试过:
pattern = r'([1-5])[abc]([1-5^\1])[abc]([1-5^\1\2])[abc]([1-5\1\2\3])[abc]([1-5\1\2\3\4])[abc]'
但是没有成功...
3 个回答
1
你可以使用负向前瞻来判断下一个数字是不是之前出现过的数字。下面这个正则表达式应该可以实现这个功能:
pattern = r'^([1-5])[abc](?!\1)([1-5])[abc](?!\1|\2)([1-5])[abc](?!\1|\2|\3)([1-5])[abc](?!\1|\2|\3|\4)([1-5])[abc]$'
补充:正如Bart所指出的,正则表达式应该以^
开头,以$
结尾,这样才能确保它只匹配完全相同的字符串。
4
你正在尝试在一个否定字符类中包含之前的匹配结果,但这是不可能的。
做到这一点的唯一方法是这样做:
^([1-5])[abc](?!\1)([1-5])[abc](?!\1|\2)([1-5])[abc](?!\1|\2|\3)([1-5])[abc](?!\1|\2|\3|\4)[1-5][abc]$
不用说,这并不是正则表达式应该做的事情。
下面是一个示例:
#!/usr/bin/env python
import re
tests = ['1a2b4a3c5b', '1a5c4b4a3b']
pattern = re.compile(
r"""(?x) # enable inline comments and ignore literal spaces
^ # match the start of input
([1-5]) # match any of '1'..'5' and store it in group 1
[abc] # match 'a', 'b' or 'c'
(?!\1)([1-5]) # if the digit from group 1 is not ahead, match any of '1'..'5' and store it in group 2
[abc] # match 'a', 'b' or 'c'
(?!\1|\2)([1-5]) # if the digits from group 1 and 2 are not ahead, match any of '1'..'5' and store it in group 3
[abc] # match 'a', 'b' or 'c'
(?!\1|\2|\3)([1-5]) # if the digits from group 1, 2 and 3 are not ahead, match any of '1'..'5' and store it in group 4
[abc] # match 'a', 'b' or 'c'
(?!\1|\2|\3|\4)[1-5] # if the digits from group 1, 2, 3 and 4 are not ahead, match any of '1'..'5'
[abc] # match 'a', 'b' or 'c'
$ # match the end of input
""", re.X)
for t in tests:
if re.match(pattern, t):
print t
将会输出:
1a2b4a3c5b
4
我建议用这样的方式来代替正则表达式:
def matches(s):
return (len(s) == 10 and
set(s[::2]) == set('12345') and
set(s[1::2]) <= set('abc'))
>>> matches('1a2b4a3c5b')
True
>>> matches('1a5c4b4a3b')
False