首页 > 解决方案 > 如何使用 Python 3 正则表达式将工作/文件标题与可选元素匹配

问题描述

我对正则表达式有中等水平的技能——我已经在几种不同的语言中使用了它多年——但是在 Python 3.6+ 中遇到更复杂的表达式时遇到了麻烦,因为查询的多个部分可能不存在。我的正则表达式的不同部分正在相互拉锯战,但经过数夜阅读、SO 和工作后,我仍然无法匹配我所有的测试用例,它们是基本文件或工作标题。这是我需要匹配的图表:

"""

Title[ *semantic* version][ | Container/Collection (after *literal* vertical bar/pipe)]

"""

这是我的代码,精简为基本要素、正则表达式和一些测试用例:

"""

import re

titles = (
    'Title Of Program 1.2.3 | Project Name',
    'Title Of Program 1 | Project Name',
    'Title Of Program | Project Name',
    'Title Of Program 1.2.3',
    'Title Of Program',
    '2 Hard Bonus',
)

regex = re.compile(r'(^.+?)(?: ?)((?:\d+(?:\.)*)+)(?: \| )*(.*)', re.M | re.S)

for title in titles:
    try:
        match = regex.search(title)
        print('(1)', match.group(1), '(2)', match.group(2), '(3)', match.group(3))
    except AttributeError:
        print('Failed match!')

"""

第二个捕获组似乎给出了最多的问题,因为轻微的调整使其成为可选(例如,对于测试用例 3、5 和 6)使其*太*可选,并且它似乎永远不会被选中。然而,所有群体似乎都受到另一个群体变化的严重影响,这使我达到了我的经验的极限。split()我有一个使用 """ """ 和 """ """的简单解决方案,strip()但需要单独使用正则表达式来解决它,因为正则表达式模式是单个函数迭代的更大模式字典的一部分。谢谢。

标签: pythonregexpython-3.x

解决方案


这个正则表达式应该给你你想要的结果:

^(.+?) ?((?:\d+\.)*\d)?(?= \||$)(?: \| )?(.+)?$

它查找一些最小数量的字符(在第 1 组中捕获),然后是一个可选的空格和一系列以数字开头和结尾的数字和点,例如1.2.3但不是1.2.(在第 2 组中捕获)。此时使用前瞻来匹配|字符串的任何一个或结尾;这会强制正则表达式的前一部分尽可能匹配到分隔符(如果存在)(否则(.+)可以捕获字符串中第一个字符以外的所有内容)。之后,我们|将直到字符串末尾的所有字符都捕获到第 3 组中。

正则表达式 101 上的演示


推荐阅读