用智能的 Python 方式去除正则表达式中的 if elif

5 投票
1 回答
1090 浏览
提问于 2025-04-18 17:10

我有一系列的正则表达式,它们是按顺序调用的。我需要先检查第一个,然后是第二个,接着是第三个,一直到最后。我需要对匹配到的字符串进行一些处理,所以我想尽量避免太复杂的逻辑。不过在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部分与前面的不同之处,然后创建一个可以循环遍历的列表。

撰写回答