【问题标题】:Match two groups but none of them should be empty匹配两个组,但它们都不应该为空
【发布时间】:2016-10-05 21:14:58
【问题描述】:

我希望我的正则表达式能够匹配随机字符的字符串(可选地后跟一些数字) - 但如果两个匹配项均为空,我希望匹配失败。我目前正在构建正则表达式:

regex = u'^(.*)'
if has_digits: regex += u'(\d*)'
regex += ext + u'$' # extension group as in u'(\.exe)'
rePattern = re.compile(regex, re.I | re.U)

但这也匹配空文件名(仅带有扩展名)。无法解决类似的问题,例如:

额外的麻烦是第二组(数字)可能不会被添加

如此有效:

abc%.exe
123.exe

如果 has_digits 为真:

abc 123.exe # I want the second group to contain the 123 not the first one

无效:.exe

【问题讨论】:

  • 你不能用+ 替换* 运算符吗?
  • @FedericoPiazza 否,因为即使 has_digits 为真,数字也可能不存在 - 如果 has_digits 为真,则第一组是可选的 如果有一些数字
  • 你能展示一些有效/无效的样本匹配吗?
  • @Tim 组因 has_digits 而异
  • @revo: 这不是说它会匹配.exe 吗?那不是? 使第一个匹配成为可选的吗?

标签: python regex python-2.7 regex-lookarounds


【解决方案1】:

正则表达式:

^(.*?)(\d+)?(?<=.)\.exe$

正向后视确保在扩展部分之前至少有一个字符。

Live demo

综合:

regex = '^(.*?)'
if has_digits: regex += '(\d+)?'
regex += '(?<=.)' + ext + '$'
rePattern = re.compile(regex, re.I | re.U)

【讨论】:

  • 谢谢 - 是什么?在(.*?) 做吗?是否等同于 (.*)? ?编辑:点击您的链接 - 解释所有内容:) 让我测试一下...
  • 还是不太确定?需要 - 如果我省略它,它会吃掉数字?
  • (.*?)(.*)? 的不同之处在于 .*? 是一个非贪婪的点星量词(它根本不消耗任何字符),但 (.*)? 是一个贪婪的点星量词尽可能多地消耗字符(第二组没有捕获数字的原因)。后者通过将? 附加到分组构造来成为可选的。
【解决方案2】:

您可以使用这个基于前瞻的正则表达式:

ext = r'\.exe'

regex = r'^(?=.+\.)(.*?)'
if has_digits: regex += r'(\d*)'
regex += ext + '$'
rePattern = re.compile(regex, re.I | re.U)
# ^(?=.+\.)(.*?)(\d*)\.exe$

RegEx Demo

Lookahead (?=.+\.) 确保在 DOT 之前至少存在一个字符。

【讨论】:

  • 谢谢 - 有趣的变化 - 只是 @revo 先到了 :)
  • 是的,这也有效。由于前瞻且没有可选组,这会更快一些。
  • 哈哈,谢谢(不接受是不公平的,但我可能会使用你的 :) 你使用 r'' 让我意识到:与标准 C 不同,所有无法识别的转义序列都会留下在字符串中不变,即反斜杠留在字符串中 -> docs.python.org/2/reference/…
猜你喜欢
  • 1970-01-01
  • 2019-02-19
  • 1970-01-01
  • 2011-04-08
  • 1970-01-01
  • 2011-06-07
  • 1970-01-01
  • 2012-05-24
  • 1970-01-01
相关资源
最近更新 更多