正则表达式子问题

3 投票
4 回答
731 浏览
提问于 2025-04-15 11:46

好吧,我遇到了一个有点奇怪的问题,跟 re.sub 有关。

看看下面这段代码:

import re
str_to_be_subbed = r'somefile.exe -i <INPUT>'
some_str = r'C:\foobar'
s = re.sub(r'\<INPUT\>', some_str, str_to_be_subbed)
print s

我本以为它会给我:

somefile.exe -i C:\\foobar

但实际上它给了我:

somefile.exe -i C:♀oobar

我知道 \f 是一个转义字符,但即使我尝试这样做,应该可以转义特殊字符。即使我这样做:

print r'%s' % s

它还是给了我这个:

somefile.exe -i C:♀oobar

为什么会这样呢?有什么好的方法可以避免这个问题吗?

补充说明:

如果我查看 s 的值,它是:

'somefile.exe -i C:\x0coobar'

为什么 \f 变成了 \x0。真让人烦。

再补充:

还有一个问题,如果我把代码改成这样:

import re
import os
str_to_be_subbed = r'somefile.exe -i <INPUT>'
some_str = os.path.abspath(r'C:\foobar')
some_str
s = re.sub(r'\<INPUT\>', some_str, str_to_be_subbed)
print s

结果是:

>>> import re
>>> import os
>>> str_to_be_subbed = r'somefile.exe -i <INPUT>'
>>> some_str = os.path.abspath(r'C:\foobar')
>>> some_str
'C:\\foobar'
>>> s = re.sub(r'\<INPUT\>', some_str, str_to_be_subbed)
>>> print s
somefile.exe -i C:♀oobar

这又是为什么呢?因为 os.path.abspath 会转义 \'s。为什么 re.sub 还是会出错呢?

另外,这只是一个很小的例子,问题在一个比较老的应用程序中突然出现。我不能随便把它改成 string.replace,因为这样改的话可能要花一整天的时间。

我只是很好奇,为什么会出现这个问题。关于上面提到的情况。

4 个回答

2

Python文档中提到...

re.sub(pattern, repl, string, count=0, flags=0) 这个函数的作用是:它会在字符串中找到最左边的、不重叠的符合模式的部分,然后用你提供的替代内容来替换。如果找不到这个模式,字符串就会保持不变。替代内容可以是一个字符串,也可以是一个函数;如果是字符串的话,里面的反斜杠转义字符会被处理。也就是说,像\n会被转换成一个换行符,\r会被转换成回车符,其他不认识的转义字符,比如\j,就不会被处理。

这就是为什么它会返回'C:♀oobar'的原因。

但是如果我们把一个函数作为第二个参数传进去,它就不会处理任何反斜杠转义字符了。

所以可以试试下面的代码...

>>>import re
>>>str_to_be_subbed = r'somefile.exe -i <INPUT>'
>>>some_str = r'C:\foobar'
>>>s = re.sub(r'\<INPUT\>', lambda _:some_str, str_to_be_subbed)
>>>print s
somefile.exe -i c:\foobar
3

不要使用正则表达式:

print str_to_be_subbed.replace("<INPUT>",some_str)

正如文档中所说:

repl可以是一个字符串或者一个函数;如果它是字符串,那么其中的反斜杠转义字符会被处理。

3

\f 是一个叫做 换页符 的字符。把它转义一下就能正常使用了:

some_str = r'C:\\foobar'

还有一种解决办法:

s = re.sub(r'<INPUT>', some_str.encode("string_escape"), str_to_be_subbed)

撰写回答