Python 正则表达式中的可选匹配
正在尝试将这些输入字符串匹配到三个匹配组(): 因此,对输入字符串的剖析如下:Python 正则表达式中的可选匹配,python,regex,Python,Regex,正在尝试将这些输入字符串匹配到三个匹配组(): 因此,对输入字符串的剖析如下: 带有自由文本的可选第一部分,直到带有周围空白(-)的连字符或输入字符串结束 可选的第二部分,第一个连字符后有任意字符,周围有空格,直到逗号或输入字符串结束 可以选择在末尾正好两位数字 我尝试了大量不同的解决方案,这是我目前的尝试: ^(?P<x>.*)(?:-)(?P<y>.*)(?<!\d)(?P<z>\d{0,2})(?!\d)$ ^(?P.*)(?:-)(?P.*
- 带有自由文本的可选第一部分,直到带有周围空白(
)的-
连字符或输入字符串结束
- 可选的第二部分,第一个连字符后有任意字符,周围有空格,直到
逗号或输入字符串结束
- 可以选择在末尾正好两位数字
^(?P<x>.*)(?:-)(?P<y>.*)(?<!\d)(?P<z>\d{0,2})(?!\d)$
^(?P.*)(?:-)(?P.*)(?\d{0,2})(?!\d)$
它处理场景II
、IV
和V
正常(也必须对空白进行一些修整),但是:
和I
根本不返回VI
不是在第一个连字符处拆分,而是在最后一个连字符处拆分III
- 这似乎做得相当不错:
^(?:(.*?)(?: - |$))?(?:(.*?)(?:, |$))?(\d\d$)?$
感兴趣的值将分别位于第1组、第2组和第3组
唯一的罪魁祸首是“两位数”将被删除
- 第2组为病例V和
- 在病例VI的第1组中
^(?:((?!\d\d$).*?)(?: - |$))?(?:((?!\d\d$).*?)(?:, |$))?(\d\d$)?$
细分: ^ # 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 ^#字符串开始 (?:(.*?)(?: - |$))? # 任何文本,不情愿地,和“-”或字符串结束 (?:(.*?)(?:, |$))? # 任何文本,不情愿地,和“,”或字符串结束 (\d\d$)?#两位数,字符串结束 $#字符串结束
实现此任务的详细正则表达式较少,但这一个以非常简单的方式对逻辑进行编码:
^(?P<x>(?!\d\d$)(?:(?! - ).)*)?(?: - (?P<y>(?!\d\d$)[^,\n]*)?(?:, )?)?(?P<z>\d\d)?$
^(?P(?!\d\d$)(?:(?!-)*)(?:-(?P(?!\d\d$)[^,\n]*)(?:,)?(?P\d\d)$
^#断言字符串/行的开头
(?P#捕获在“x”组中)
(?!\d\d$)#如果整个字符串只有两位数字,请不要在组x中捕获它们
(?:#只要。。。
(?!-)#…我们没有看到文本“-”。。。
.#…使用下一个角色
)*
)? # 将组x设为可选
(?:#如果可能的话。。。
-#使用“-”分隔符
(?P#然后捕获组“y”
(?!\d\d$)#仅当这不是属于组z的两位数字时
[^,\n]*#把所有东西都消耗到一个逗号
)?#y组也是可选的
(?:,)?#使用“,”分隔符(如果存在)
)?
(?P#最后,在“z”组中捕获。。。
\d\d#…两位数。。。
)? # ...如有
$#断言字符串的结尾
有趣的问题,这是我提出的解决方案:
^
(?:(?P<x>\D*?)(?=(?:\ -\ |$)))?
(?:.*?(?<=\ -\ )(?P<y>[^\d,]+)(?=,|$))?
(?:.*?(?P<z>\d{2}$))?
$
您可以使用
?
字符来指示可选字符(组)。另请参见。可以通过将第二组更改为(?:\s+-\s+
)来解决III的问题,因此实际会测试空白。但是你的规范说了或,并且有几次是可选的,我没有看到可选的组。一些断言是的,但不足以满足您的需要。预先筛查可以通过简单的^[\w]+$
检查发现病例I和VI。试试看:^(?P[a-z]*)(\s\-\s)?(?P[a-z\-]*)(,\s)?(?P\d{0,2})?$
。您说第二组可以包含任何字符,但显然不能,因为您还说第二组和第三组由逗号分隔。这意味着您的正则表达式定义不明确。另外,你应该清楚“自由文本”的含义,而不仅仅是匹配*
。你能为b,12
添加预期结果吗?回答得好。关于“自由文本直到分隔符,或者直到字符串结束”子句匹配数字,我也在为同样的歧义而挣扎。这是我在使用正则表达式时经常使用的一个方便的站点上的你的建议。(请不要在没有留下错误评论的情况下进行否决。谢谢。)好的解决方案!将命名组保存在适当的存储桶中会很好,因为我必须对类型进行后期检查。我没有否决投票,但这个答案可能来得有点太快,因为问题中的正则表达式定义被破坏了。它在第二部分提到了“任何角色”,但第三部分也在第二部分之后。根据“任何字符”的定义,第三部分永远无法匹配,并且将始终包含在第二部分中。所以正则表达式的定义真的需要一些澄清。啊,很抱歉这种含糊不清。希望这能澄清问题:“两位数字”具有优先权(即,如果II
中的“b”正好等于两位数字,那么我们将其归类为z
-组)。这一答案避免了第1组和第2组的两位数字是非法值。这不是要求的一部分,所以。。。(评论比否决票好,不是吗?特别是当有多种解释问题的方法时)你应该删除这个非捕获组:(?=(?:\-\ \ \ \ \$)
(?=\-\ \ \ \ \ \$)
,因为它是无用的。@casimirithippolyte:是的,删除了。
^ # assert start of string/line
(?P<x> # capture in group "x"
(?!\d\d$) # if the whole string is just two digits, don't capture them in group x
(?: # as long as...
(?! - ) # ...we don't come across the text " - "...
. # ...consume the next character
)*
)? # make group x optional
(?: # if possible...
- # consume the " - " separator
(?P<y> # then capture group "y"
(?!\d\d$) # again, only if this isn't two digits which belong in group z
[^,\n]* # consume everything up to a comma
)? # group y is also optional
(?:, )? # consume the ", " separator, if present
)?
(?P<z> # finally, capture in group "z"...
\d\d # ...two digits...
)? # ...if present
$ # assert end of string
^
(?:(?P<x>\D*?)(?=(?:\ -\ |$)))?
(?:.*?(?<=\ -\ )(?P<y>[^\d,]+)(?=,|$))?
(?:.*?(?P<z>\d{2}$))?
$
^ # start of the line
(?: # non capturing parentheses
(?P<x>\D*?) # no digits lazily ...
(?=\ -\ |$) # up until either " - " or end of string
)? # optional
(?:
.*? # match everything lazily
(?<=\ -\ ) # pos. lookbehind
(?P<y>[^\d,]+) # not a comma or digit
(?=,|$) # up until a comma or end of string
)?
(?:
.*?
(?P<z>\d{2}$) # two digits at the end
)?
$