python regex-积极向前看

时间:2017-11-14 12:30:13

标签: python regex

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'

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

2 个答案:

答案 0 :(得分:1)

您认为&第一次匹配的假设基本上是错误的。

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

#34的常见修复;我希望尽可能少&#34;是使用贪婪的量词.+?,这意味着匹配尽可能少 但它仍然可能最终匹配你不想要的东西。

如果你的意思是&#34;匹配第一个&&#34;那么除了&&#34;。

之外你应该重复的表达式
ptn=r'(?<=realname=)[^&]+(?=&)'

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

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

答案 1 :(得分:0)

使用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?