首页 > 解决方案 > 正则表达式:是否可以通过一个正则表达式获取可选部分中的数字

问题描述

我有一个字符串,它会像:1A2B3Cor 2B3Cor 1A2Bor 1A3C

该字符串由 的多个可选部分组成number + [A|B|C]

可以使用一个正则表达式在每个字符之前获取数字吗?

例如:

1A2B3C => (1, 2, 3)
1A3C => (1, 0, 3) There is no 'B', so gives 0 instead. 
     => Or just (1, 3) but should show that the 3 is in front of 'C'.

标签: regex

解决方案


假设 Python 是因为您的元组表示法,并且因为这就是我喜欢使用的。

如果唯一允许的字母是A,BC,您可以通过额外的处理步骤来做到这一点:

pattern = re.compile(r'(?:(\d+)A)(?:(\d+)B)?(?:(\d+)C)?')
match = pattern.fullmatch(some_string)
if match:
    result = tuple(int(g) for g in match.groups('0'))
else:
    raise ValueError('Bad input string')

每个选项都被一个非捕获组包围,(?:...)因此整个事物都被视为一个单元。单元内部有一个捕获组(\d+),用于捕获数字,以及一个未捕获的字符。

该方法Matcher.groups返回正则表达式中所有组的元组,不匹配的组设置为“0”。然后生成器int为您转换为一个。你可以使用tuple(map(int, match.groups('0'))).

您还可以使用字典来保存按字符键入的数字:

pattern = re.compile(r'(?:(?P<A>\d+)A)(?:(?P<B>\d+)B)?(?:(?P<C>\d+)C)?')
match = pattern.fullmatch(some_string)
if match:
    result = {k: int(v) for k, v in match.groupdict('0').items()}
else:
    raise ValueError('Bad input string')

Matcher.groupdict就像groups它返回一个命名组的字典:捕获标记的组(?P<NAME>...)

最后,如果您不介意使用字典,您可以采用这种方法来解析任意数量的具有任意字符的组:

pattern = re.compile(r'(\d+)([A-Z])')
result = {}
while some_string:
    match = pattern.match(some_string)
    if not match:
        raise ValueError('Bad input string')
    result[match.group(2)] = int(match.group(1))
    some_string = some_string[match.end():]

推荐阅读