用智能的 Python 方式去除正则表达式中的 if elif
我有一系列的正则表达式,它们是按顺序调用的。我需要先检查第一个,然后是第二个,接着是第三个,一直到最后。我需要对匹配到的字符串进行一些处理,所以我想尽量避免太复杂的逻辑。不过在Python中,与Perl不同,我觉得我不能在if-elif-elif
这样的结构里直接进行赋值,所以我最后只能先赋值,然后再检查是否匹配,最后再获取匹配的结果。例如:
m = re.search(patternA, string)
if m:
stripped = m.group(0)
xyz = stripped[45:67]
elif:
m = re.search(patternB, string)
if m:
stripped = m.group(0)
abc = stripped[5:7]
elif:
m = re.search(patternB, string)
if m:
stripped = m.group(0)
txt = stripped[4:5]
elif:
......
理想情况下,我希望能找到一个更好的结构,这样可以确保我测试的正则表达式的顺序不变,并且可以把赋值放进if-then语句里。所以例如:
if (m = re.search(patternA, string)):
stripped = m.group(0)
xyz = stripped[45:67]
elif (m = re.search(patternB, string)):
stripped = m.group(0)
abc = stripped[5:7]
...
处理这个问题最符合Python风格的方法是什么呢?谢谢。
这个用例是为了读取旧数据——非常旧的数据。不过每个字符串可能包含特定值的信息,而这些信息只有在正则表达式匹配特定模式时才会出现。因此,提取的变量高度依赖于匹配的结果。
1 个回答
2
for (pattern, slice) in zip([patternA, patternB, patternC],
[slice(45,67), slice(5,7), slice(4,5)]):
m = re.search(pattern, string)
if m:
value = m.group(0)[slice]
break
else:
# Handle no match found for any pattern here
这个代码会逐对检查正则表达式和它们匹配的相关部分,直到找到一个匹配项。如果没有找到匹配项,for
循环的else
部分就会执行。无论哪个模式匹配,匹配的结果都会在循环结束后保存在value
中。
根据哪个“分支”成功来设置不同的变量并不是个好主意,因为你可能不知道在任何时刻哪些变量是被设置的。如果你真的想为每个匹配项使用不同的标签,使用字典会更好,因为你可以查询字典中哪些键被设置了。
value = {}
for (pattern, slice, key) in zip([patternA, patternB, patternC],
[slice(45,67), slice(5,7), slice(4,5)],
['abc', 'xyx', 'txt']):
m = re.search(pattern, string)
if m:
value[key] = m.group(0)[slice]
break
总的来说,你需要注意的是,你的if
语句链就像是硬编码的循环,所以你只需要找出每个if/elif
部分与前面的不同之处,然后创建一个可以循环遍历的列表。