【问题标题】:python regex look ahead positive + negativepython 正则表达式向前看正面+负面
【发布时间】:2016-02-08 09:46:35
【问题描述】:

这个正则表达式将得到 456。我的问题是为什么它不能是 234 from 1-234-56 ? 56 是否符合 (?!\d)) 模式,因为它不是单个数字。 (?!\d)) 将寻找的起点在哪里?

import re
pattern = re.compile(r'\d{1,3}(?=(\d{3})+(?!\d))')
a = pattern.findall("The number is: 123456") ; print(a)

在第一阶段添加逗号分隔符,如 123,456。

a = pattern.findall("The number is: 123456") ; print(a)
results = pattern.finditer('123456')
  for result in results:
    print ( result.start(), result.end(), result)

【问题讨论】:

  • 如果你告诉你期望正则表达式做什么会有所帮助
  • 你是怎么得到123-456的?
  • ?! 是负前瞻标记,因此如果没有一位数,?!\d 将前瞻
  • 感谢 SIslam。我只是好奇为什么不能像 1-234-56 那样解析整个数字,因为 ?!\d 只排除 SINGLE 数字,56 不是一个数字。
  • 认为你的正则表达式有错误,因为当我运行import re pattern = re.compile(r'\d{1,3}(?=(\d{3})+(?!\d))') a = pattern.findall("The number is: 123456") print(a) 我得到['456']

标签: python regex regex-lookarounds


【解决方案1】:

我的问题是为什么它不能是来自1-234-56234

这是不可能的,因为(?=(\d{3})+(?!\d)) 要求在 1-3 位序列之后出现 3 位序列。 56(您想象的场景中的最后一个数字组)是一个两位数的组。由于量词既可以是惰性的也可以是贪婪的,因此您不能将一位、两位和三位数字组都与\d{1,3} 匹配。要从123456 获取234,您需要专门为其定制的正则表达式:\B\d{3},或(?<=1)\d{3},甚至\d{3}(?=\d{2}(?!\d))

56 是否匹配 (?!\d)) 模式? (?!\d)) 将寻找的起点在哪里?

不,这是一个否定的前瞻,它不匹配,它只检查输入字符串中当前位置之后是否没有数字。如果有数字,则匹配失败(未找到并返回结果)。

关于前瞻的更多说明:它位于(\d{3})+ 子模式之后,因此正则表达式引擎在最后一个 3 位组之后开始搜索一个数字,如果找到该数字则匹配失败(因为它是负前瞻)。简单来说,(?!\d) 是此正则表达式中的数字关闭/尾随边界

更详细的细分:

  • \d{1,3} - 1 到 3 位序列,尽可能多(使用贪心量词)
  • (?=(\d{3})+(?!\d)) - 一个正向前瞻 ((?=...)),检查之前匹配的 1-3 位序列是否后跟
    • (\d{3})+ - 1 个或多个 (+) 正好 3 个数字的序列...
    • (?!\d) - 后面没有数字。

Lookaheads 不匹配,不消耗字符,但您仍然可以在其中捕获。执行前瞻时,正则表达式索引与之前的字符相同。 使用您的正则表达式和输入,您可以将 123\d{1,3} 匹配,因为您有 3 位序列 (456)。但是456 在前瞻中被捕获,如果设置了捕获组,re.findall 仅返回捕获的文本。

要仅添加逗号作为数字分组符号,请使用

rx = r'\d(?=(?:\d{3})+(?!\d))'

IDEONE demo

【讨论】:

  • 不是我的。 :-) 对于之前的不准确问题,我深表歉意。已经修好了。
  • @Ascanio:它回答了你的问题吗?或者您是否需要进一步说明 (?!\d) 的工作原理?
  • 是的,请!你最懂我心!这是问题的根本原因。
  • @Ascanio:我添加了更多说明,并更新了“主要”问题答案。
  • 您的理解有误。你还没有读过re.findall。前瞻不匹配,不消耗字符,但您仍然可以在其中捕获。执行前瞻时,正则表达式索引与之前的字符相同。您将 123\d{1,3} 匹配,因为您有 3 位序列 (456)。但是456 在前瞻中被捕获,如果设置了捕获组,re.findall 仅返回捕获的文本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-29
  • 1970-01-01
  • 2018-03-07
  • 2014-10-15
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
相关资源
最近更新 更多