匹配交替的数字和字符

2 投票
3 回答
1162 浏览
提问于 2025-04-17 00:08

我看过谷歌的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

撰写回答