正则表达式中的可选匹配

sal*_*ent 4 python regex

尝试将这些输入字符串匹配到三个匹配组(Regex101链接):

    | input string  | x  | y   | z  |
------------------------------------
  I | a             | a  |     |    |
 II | a - b         | a  | b   |    |
III | a - b-c       | a  | b-c |    |
 IV | a - b, 12     | a  | b   | 12 |
  V | a - 12        | a  |     | 12 |
 VI | 12            |    |     | 12 |
Run Code Online (Sandbox Code Playgroud)

所以输入字符串的解剖结构如下:

  • 可选的第一部分,带有自由文本,直到hyphen带有周围的空格(-)输入字符串结束
  • 可选的第二部分,在第一个连字符后面有任何字符,周围有空格,直到a comma或输入字符串结束
  • 最后可选两个数字

我尝试过多种不同的解决方案,这是我目前的尝试:

^(?P<x>.*)(?:-)(?P<y>.*)(?<!\d)(?P<z>\d{0,2})(?!\d)$
Run Code Online (Sandbox Code Playgroud)

它处理场景II,IV然后V确定(必须对白色空间进行一些修整),但是:

  • I并且VI根本不归还
  • III 不是在第一个连字符处分开,而是在最后一个连字符处分开

Tom*_*lak 5

这看起来相当不错:

^(?:(.*?)(?: - |$))?(?:(.*?)(?:, |$))?(\d\d$)?$
Run Code Online (Sandbox Code Playgroud)

感兴趣的值将分别在第1,2和3组中.

唯一的罪魁祸首是"两位数"

  • 案件V和案件的第2组
  • 在案例VI的第1组中,

在这些情况下,其他群体是空的.

这是因为"两位数"很乐意匹配"自由文本直到分隔符或字符串结束"规则.

您可以使用负向预测强制将两个数字强制转换为最后一个组,但除非"两个数字"不是第1组和第2组的合法值,否则这将不正确.在任何情况下,它都会使表达方式变得笨拙:

^(?:((?!\d\d$).*?)(?: - |$))?(?:((?!\d\d$).*?)(?:, |$))?(\d\d$)?$
Run Code Online (Sandbox Code Playgroud)

分解:

^                    # string starts
(?:(.*?)(?: - |$))?  # any text, reluctantly, and " - " or the string ends
(?:(.*?)(?:, |$))?   # any text, reluctantly, and ", " or the string ends
(\d\d$)?             # two digits and the string ends
$                    # string ends