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'
。我做错了什么?
答案 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?