【问题标题】:functional difference between lookarounds and non-capture group?环视和非捕获组之间的功能差异?
【发布时间】:2018-02-07 05:59:44
【问题描述】:

我正在尝试提出一个正面环顾四周有效的示例,但 非捕获组将不起作用,以进一步了解它们的用法。我提出的示例也适用于非捕获组,所以我觉得我没有完全掌握积极环顾四周的用法。

这是一个字符串(取自一个 SO 示例),它在答案中使用正向预测。用户想要获取第二列的值,只有当 第一列以 ABC 开头,最后一列的值为“活动”。

string ='''ABC1    1.1.1.1    20151118    active
          ABC2    2.2.2.2    20151118    inactive
          xxx     x.x.x.x    xxxxxxxx    active'''

给出的解决方案使用“积极展望”,但我注意到我可以使用非捕获组来得出相同的答案。 所以,我很难想出一个正面环顾工作,非捕获组不起作用的例子。

pattern =re.compile('ABC\w\s+(\S+)\s+(?=\S+\s+active)') #solution

pattern =re.compile('ABC\w\s+(\S+)\s+(?:\S+\s+active)') #solution w/out lookaround

如果有人愿意提供一个例子,我将不胜感激。

谢谢。

【问题讨论】:

  • 这将与前瞻之后的内容有关。前瞻是零宽度(我认为)而不是非捕获。
  • 一个组(捕获或非捕获)使用字符串。环视不会。

标签: python regex python-3.x regex-lookarounds regex-group


【解决方案1】:

根本区别在于,非捕获组仍然消耗它们匹配的字符串部分,从而向前移动光标。

其中一个根本不同的例子是,当您尝试匹配某些字符串时,这些字符串被某些边界包围并且这些边界可以重叠。示例任务:

匹配给定字符串中被bs 包围的所有as - 给定字符串是bababaca。应该有两个匹配,在位置 2 和 4。

使用环视很容易,您可以使用b(a)(?=b)(?<=b)a(?=b) 并匹配它们。但是(?:b)a(?:b) 不起作用 - 第一场比赛也会消耗位置 3 的 b,这是第二场比赛的边界。 (注意:这里实际上不需要非捕获组)

另一个相当突出的示例是密码验证 - 检查密码是否包含大写、小写字母、数字等 - 您可以使用一堆替换来匹配这些 - 但前瞻更容易:

(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!?.])

(?:.*[a-z].*[A-Z].*[0-9].*[!?.])|(?:.*[A-Z][a-z].*[0-9].*[!?.])|(?:.*[0-9].*[a-z].*[A-Z].*[!?.])|(?:.*[!?.].*[a-z].*[A-Z].*[0-9])|(?:.*[A-Z][a-z].*[!?.].*[0-9])|...

【讨论】:

  • 这真的很有帮助。太感谢了!我在理解第二个示例时遇到了一些麻烦。 (?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=[!?.]) 强制密码至少包含一个小写字母,一个大写字母。一位数等?由于环顾四周不消耗任何东西,我们最终得到一个空匹配,对吗?我尝试在模式末尾添加一个 '\S+' 以查看是否会捕获此字符串 string = 'AZN###3232!abbb32.....'',但我最终得到一个空匹配。我假设应该捕获我的整个字符串。
  • 好吧,我在最后的前瞻中忘记了.*。是的,您可能希望将它与锚点和 .+\S+ 一起使用以匹配整个字符串。
  • 很好的例子! ...除了我们不应该再检查密码格式:NIST 有deprecated this practice
猜你喜欢
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
  • 2018-06-28
  • 1970-01-01
  • 2011-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多