Python 正则表达式:Lookbehind + Lookahead with characterset

Python regex: Lookbehind + Lookahead with characterset

我想将字符串 10M5D8P 放入字典中:

M:10, D:5, P:8 等...

字符串可能更长,但它始终是一个数字后跟一个来自该字母表的单个字母:MIDNSHP=X

作为第一步,我想用后向和前向拆分字符串,在这两种情况下都匹配这个正则表达式:[0-9]+[MIDNSHP=X]

所以我目前无法使用的解决方案如下所示:

重新导入

re.compile("(?<=[0-9]+[MIDNSHP=X])(?=[0-9]+[MIDNSHP=X])").split("10M5D8P ")

它给了我一条我不明白的错误信息:"look-behind requires fixed-width pattern"

您可以使用 re.findall。

>>> import re
>>> s = "10M5D8P"
>>> {i[-1]:i[:-1] for i in re.findall(r'[0-9]+[MIDNSHP=X]', s)}
{'M': '10', 'P': '8', 'D': '5'}
>>> {i[-1]:int(i[:-1]) for i in re.findall(r'[0-9]+[MIDNSHP=X]', s)}
{'M': 10, 'P': 8, 'D': 5}

您的正则表达式将无法工作,因为 re 模块将不支持可变长度回顾断言。而且它也不支持在零宽度边界上分割,所以这个(?<=\d)(?=[A-Z])也不可能。

look-behind requires fixed-width pattern 的意思就是它所说的 - 后视模式必须匹配 Python 引擎中固定数量的字符。特别是,它不允许包含任何量词(?+*)。因此,我们应该选择一个固定宽度的片段作为我们的回顾:

(?<=[MIDNSHP=X])(?=\d)

这仅使用单个字符作为后视,使用单个数字作为前视。但是,如果您尝试使用此表达式 split,它将因 Python bug 3262 而失败。您需要改用这样的解决方法:

>>> re.compile(r"(?<=[MIDNSHP=X])(?=\d)").sub('|', '10M5D8P').split("|")
['10M', '5D', '8P']

但这很难看。一个更简单的解决方案是使用findall提取你想要的:

>>> re.findall('([0-9]+)([MIDNSHP=X])', '10M5D8P')
[('10', 'M'), ('5', 'D'), ('8', 'P')]

您可以很容易地从中创建字典:

>>> {k:int(v) for v,k in re.findall('([0-9]+)([MIDNSHP=X])', '10M5D8P')}
{'P': 8, 'M': 10, 'D': 5}