【问题标题】:python regex- positive lookaheadpython 正则表达式-正向前瞻
【发布时间】:2017-11-15 20:35:15
【问题描述】:
str='filename=1817616353&realname=Arguments%20for%20&%20against%20protection%20.pdf&code2=pds'
ptn='(?<=realname=).+(?=&)'
re.search(ptn,str).group()

好吧,当我运行这段代码时,我期望得到

'Arguments%20for%20'

作为匹配,但它给了我

'Arguments%20for%20&%20against%20protection%20.pdf'

我认为匹配应该发生在'&amp;' 的第一次出现时,它就在'for%20' 部分之后,所以我不知道为什么它会一直下降到'pdf'。我做错了什么?

【问题讨论】:

    标签: python regex


    【解决方案1】:

    您认为&amp; 的第一次出现会匹配的假设从根本上是错误的。

    .+ 表示匹配尽可能多的任何字符(换行符除外)。因此这会导致它之后的任何内容在最后 可能的位置。

    “我想要尽可能少”的常见解决方法是使用贪婪量词.+?,这意味着匹配尽可能少,但它仍然可以结束匹配你不想要的东西。

    如果您的真正意思是“匹配第一个可能的&amp;”,那么您应该在它之前重复的表达式是“除&amp; 之外的任何内容”。

    ptn=r'(?<=realname=)[^&]+(?=&)'
    

    (还要注意r'...' 字符串的使用。在这里它没有任何区别,但这是另一个常见的新手错误——你想在你的正则表达式中使用反斜杠并且不明白为什么 Python 会丢失它们。)

    这基本上是对the other answer on this page 的重述,但希望初学者更容易理解。

    【讨论】:

      【解决方案2】:

      使用negated character class 代替.+

      In [5]: ptn='(?<=realname=)[^&]+(?=&)'
      
      In [6]: re.search(ptn,str).group()
      Out[6]: 'Arguments%20for%20'
      

      虽然您可以通过在.* 的尾随添加? 来使用非贪婪量词,但在这种情况下使用否定字符类会给您带来更好的性能:

      In [7]: ptn='(?<=realname=).+?(?=&)'
      
      In [9]: %timeit re.search(ptn,str).group()
      1000000 loops, best of 3: 1.46 us per loop
      
      In [10]: ptn='(?<=realname=)[^&]+(?=&)'
      
      In [11]: %timeit re.search(ptn,str).group()
      1000000 loops, best of 3: 1.18 us per loop
      

      有关更多信息,请阅读以下关于非贪婪量词和否定字符类之间的区别的帖子。 Which would be better non-greedy regex or negated character class?

      【讨论】:

      • @downvoter,当您遇到an answer that is clearly and perhaps dangerously incorrect时,请使用您的否决权。
      • 我不是反对者(恰恰相反),但也许会提到 OP 对正则表达式的工作方式存在根本性的误解。期望&amp; 的第一次出现应该匹配是完全错误的,并且典型的是不理解最长最左匹配+回溯,这是相当基本的概念。
      • @tripleee 确实!这就是为什么我首先建议使用否定字符类而不是惰性匹配。 (无论其性能如何)因为它不仅可以帮助 OP 了解解决方案,而且还可以在他们的脑海中提出很多问题,从而理解这些概念。
      • 我可以建议编辑还是您希望我发布单独的答案?
      • @tripleee 没有你的答案是在解释潜在的误解,绝对值得单独回答。
      猜你喜欢
      • 1970-01-01
      • 2018-12-28
      • 2012-04-14
      • 1970-01-01
      • 1970-01-01
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多