“没有扩展名的选择文件名”的否定预测

时间:2012-11-27 06:35:11

标签: python regex negative-lookahead

我需要在href="xxx"中的所有网址中添加“php”,但不以“php”结尾。
我使用negetive lookahead (?!php)

find = r'href="(.+?)(?!php)"'
replace =  r'href="\1.php"'
re.sub(find, replace, 'href="url"')
re.sub(find, replace, 'href="url.php"')

都添加扩展名:

href="url.php"
href="url.php.php"

为什么负向前瞻不起作用?

2 个答案:

答案 0 :(得分:4)

以下工作正常:

In [49]: re.sub(r'href="([^"]*?)([.]php)?"', r'href="\1.php"', 'href="url.php"')
Out[49]: 'href="url.php"'

In [50]: re.sub(r'href="([^"]*?)([.]php)?"', r'href="\1.php"', 'href="url"')
Out[50]: 'href="url.php"'

原始正则表达式(.+?)(?!php)不起作用的原因是它与url.php匹配如下:

  • (.+?)匹配url.php;
  • 此时由于下一个字符是双引号,因此满足否定前瞻。

换句话说,.+?会占用包含扩展名在内的整个文件名,使前瞻变为无操作。

答案 1 :(得分:1)

否定前瞻意味着正则表达式尝试匹配下一个模式,但不消耗该模式。您的模式"(.+?)(?!php)"匹配任意数字的1个或多个字符,直到它符合",然后尝试匹配下一个模式,即php。这个前瞻总是会失败,因为下一个字符是",因为这是一个负面的预测,所以整个模式都会成功。

你需要的是负面的后视,((?<!PATTERN)),它将尝试匹配角色消耗后的模式。当它遇到"时,lookbehind模式会尝试将最后3个字符与模式php进行匹配。

简而言之,请以下面的模式重试

find = 'href="(.+?)(?<!php)"'