在格式错误的字符串上使用 Regex 进行解析
Parsing with Regex on badly formatted string
我正在解析 Python 中的一个大文件,其中包含如下行:
"Value names: 0 = Something, 1 = Something, else, 4 = A value, 5 = BAD - enough, 6 GOOD, 7 = Ugly,"
我的目标是将它们放入字典中。
问题是它们的写法根本不一致,其中一些缺少逗号、等号等。而且名称中也可能有逗号之类的东西。数字(键)也可以包含几个数字。我唯一确定的是,名称中没有数字。
正因为如此,我想我会试一试正则表达式,但结果比预期的要难一些。
我试过的是这个
s = "Value names: 0 = Something, 1 = Something, else, 4 = A value 5 = BAD, 6 GOOD, 7 = Ugly,"
pattern = re.compile(r'([0-9]+)([A-Z]+)')
for (numbers, letters) in re.findall(pattern, s):
...
然而,这(对于训练有素的眼睛来说可能很明显)不起作用。
由于我不太精通正则表达式,因此我非常感谢对此提供一些帮助,因为我无法直接编辑文件,而且所有手动解析技巧似乎都不够用。
您可以使用
(?P<keys>\d+)\s*(?:=\s*)?(?P<values>.*?)(?=\s*(?:,\s*)?(?:\d|\Z))
见regex demo。 详情:
(?P<keys>\d+)
- 组“键”:一个或多个数字
\s*
- 零个或多个空格
(?:=\s*)?
- =
和零个或多个空格 的可选序列
(?P<values>.*?)
- 组“值”:除换行字符外的任何零个或多个字符,尽可能少
(?=\s*(?:,\s*)?(?:\d|\Z))
- 在当前位置的右边,必须有
\s*
- 零个或多个空格
(?:,\s*)?
- ,
和零个或多个空格 的可选序列
(?:\d|\Z)
- 数字或字符串结尾。
看到一个Python demo:
import re
text = "Value names: 0 = Something, 1 = Something, else, 4 = A value, 5 = BAD - enough, 6 GOOD, 7 = Ugly,"
pattern = r"(?P<keys>\d+)\s*(?:=\s*)?(?P<values>.*?)(?=\s*(?:,\s*)?(?:\d|\Z))"
for match in re.finditer(pattern, text):
print(match.groupdict())
输出:
{'keys': '0', 'values': 'Something'}
{'keys': '1', 'values': 'Something, else'}
{'keys': '4', 'values': 'A value'}
{'keys': '5', 'values': 'BAD - enough'}
{'keys': '6', 'values': 'GOOD'}
{'keys': '7', 'values': 'Ugly'}
我正在解析 Python 中的一个大文件,其中包含如下行:
"Value names: 0 = Something, 1 = Something, else, 4 = A value, 5 = BAD - enough, 6 GOOD, 7 = Ugly,"
我的目标是将它们放入字典中。
问题是它们的写法根本不一致,其中一些缺少逗号、等号等。而且名称中也可能有逗号之类的东西。数字(键)也可以包含几个数字。我唯一确定的是,名称中没有数字。
正因为如此,我想我会试一试正则表达式,但结果比预期的要难一些。
我试过的是这个
s = "Value names: 0 = Something, 1 = Something, else, 4 = A value 5 = BAD, 6 GOOD, 7 = Ugly,"
pattern = re.compile(r'([0-9]+)([A-Z]+)')
for (numbers, letters) in re.findall(pattern, s):
...
然而,这(对于训练有素的眼睛来说可能很明显)不起作用。
由于我不太精通正则表达式,因此我非常感谢对此提供一些帮助,因为我无法直接编辑文件,而且所有手动解析技巧似乎都不够用。
您可以使用
(?P<keys>\d+)\s*(?:=\s*)?(?P<values>.*?)(?=\s*(?:,\s*)?(?:\d|\Z))
见regex demo。 详情:
(?P<keys>\d+)
- 组“键”:一个或多个数字\s*
- 零个或多个空格(?:=\s*)?
-=
和零个或多个空格 的可选序列
(?P<values>.*?)
- 组“值”:除换行字符外的任何零个或多个字符,尽可能少(?=\s*(?:,\s*)?(?:\d|\Z))
- 在当前位置的右边,必须有\s*
- 零个或多个空格(?:,\s*)?
-,
和零个或多个空格 的可选序列
(?:\d|\Z)
- 数字或字符串结尾。
看到一个Python demo:
import re
text = "Value names: 0 = Something, 1 = Something, else, 4 = A value, 5 = BAD - enough, 6 GOOD, 7 = Ugly,"
pattern = r"(?P<keys>\d+)\s*(?:=\s*)?(?P<values>.*?)(?=\s*(?:,\s*)?(?:\d|\Z))"
for match in re.finditer(pattern, text):
print(match.groupdict())
输出:
{'keys': '0', 'values': 'Something'}
{'keys': '1', 'values': 'Something, else'}
{'keys': '4', 'values': 'A value'}
{'keys': '5', 'values': 'BAD - enough'}
{'keys': '6', 'values': 'GOOD'}
{'keys': '7', 'values': 'Ugly'}