Python re.sub:忽略替换字符串中的反向引用
我想用字符串替换模式。字符串在变量中给定。当然,它可能包含“\1”,不应将其解释为反向引用,而应简单地解释为\1Python re.sub:忽略替换字符串中的反向引用,python,regex,python-3.x,Python,Regex,Python 3.x,我想用字符串替换模式。字符串在变量中给定。当然,它可能包含“\1”,不应将其解释为反向引用,而应简单地解释为\1 我怎样才能做到这一点呢?由于评论的缘故,我对此思考了很久,并尝试了一下。帮助我提高了对逃跑的理解,所以我几乎完全改变了我的答案,以便对以后的读者有用 NullUserException只提供了一个简短的版本,我试着解释一下。多亏了Qtax和邓肯的批评性评论,这个答案现在有望是正确和有用的 反斜杠有一个特殊的含义,它是字符串中的转义字符,这意味着反斜杠和后面的字符构成了一个转义序列,当
我怎样才能做到这一点呢?由于评论的缘故,我对此思考了很久,并尝试了一下。帮助我提高了对逃跑的理解,所以我几乎完全改变了我的答案,以便对以后的读者有用 NullUserException只提供了一个简短的版本,我试着解释一下。多亏了Qtax和邓肯的批评性评论,这个答案现在有望是正确和有用的 反斜杠有一个特殊的含义,它是字符串中的转义字符,这意味着反斜杠和后面的字符构成了一个转义序列,当对字符串执行某些操作时,该转义序列将被转换为其他字符。这个“somethinesedone”已经是字符串的创建。因此,如果你想使用
\
字面意思,你需要逃避它。此转义字符本身就是反斜杠
因此,为了更好地理解所发生的事情,我们开始一些例子。我还额外打印了字符串中字符的ASCII码,希望能增加所发生事情的可理解性
s = "A\1\nB"
print s
print [x for x in s]
print [hex(ord(x)) for x in s]
正在印刷
A
B
['A', '\x01', '\n', 'B']
['0x41', '0x1', '0xa', '0x42']
因此,当我在代码中键入\
和1
时,s
不包含这两个字符,它包含ASCII字符0x01
,即“标题的开始”。与\n
相同,它转换为0x0a
换行字符
由于并不总是需要这种行为,因此可以使用原始字符串,而忽略转义序列
s = r"A\1\nB"
print s
print [x for x in s]
print [hex(ord(x)) for x in s]
我刚刚在字符串之前添加了r
,结果是现在
A\1\nB
['A', '\\', '1', '\\', 'n', 'B']
['0x41', '0x5c', '0x31', '0x5c', '0x6e', '0x42']
所有字符都是在我打字时打印出来的
这就是我们的情况。现在是下一件事
可能存在这样的情况,即字符串应该传递给正则表达式,以便按字面意思查找,因此正则表达式中具有特殊含义的每个字符(例如+*$[])都需要转义,因此有一个特殊的函数re.escape
来完成此工作
但是对于这个问题,这是一个错误的函数,因为该字符串不应该在正则表达式中使用,而是作为re.sub
的替换字符串
s = r"A\1\nB"
print re.sub(r"(Replace)" ,s , "1 Replace 2")
如此新的情况:
包含转义序列的原始字符串应用作re.sub
的替换字符串re.sub
也将处理转义序列,但与之前的处理有一个小但重要的区别:\n
仍然被转换为0x0a
换行字符,但\1
现在已更改!它将替换为re.sub
中正则表达式的捕获组1的内容
s = r"A\1\nB"
print re.sub(r"(Replace)" ,s , "1 Replace 2")
结果是
1 AReplace
B 2
\1
已替换为捕获组的内容,\n
已替换为换行符
重要的一点是,你必须理解这种行为,现在我认为你有两种可能性(我不会判断哪一种是正确的)
\n
,那么他需要换行符。在这种情况下,使用此选项仅转义后跟数字的\
OnlyDigits = re.sub(r"(Replace)" ,re.sub(r"(\\)(?=\d)", r"\\\\", s) , "1 Replace 2")
print OnlyDigits
print [x for x in OnlyDigits]
print [hex(ord(x)) for x in OnlyDigits
输出:
1 A\1
B 2
['1', ' ', 'A', '\\', '1', '\n', 'B', ' ', '2']
['0x31', '0x20', '0x41', '0x5c', '0x31', '0xa', '0x42', '0x20', '0x32']
1 A\1\nB 2
['1', ' ', 'A', '\\', '1', '\\', 'n', 'B', ' ', '2']
['0x31', '0x20', '0x41', '0x5c', '0x31', '0x5c', '0x6e', '0x42', '0x20', '0x32']
want to see:
hai! \1 <ops> $1 \' \x \\
getting:
hai! # <ops> $1 \' \x \
over escaped:
hai\!\ \1\ \<ops\>\ \$1\ \\'\ \x\ \\
could work:
hai! \1 <ops> $1 \' \x \\
\0xa
。在这种情况下,请全部转义
All = re.sub(r"(Replace)" ,re.sub(r"(\\)", r"\\\\", s) , "1 Replace 2")
print All
print [x for x in All]
print [hex(ord(x)) for x in All]
输出:
1 A\1
B 2
['1', ' ', 'A', '\\', '1', '\n', 'B', ' ', '2']
['0x31', '0x20', '0x41', '0x5c', '0x31', '0xa', '0x42', '0x20', '0x32']
1 A\1\nB 2
['1', ' ', 'A', '\\', '1', '\\', 'n', 'B', ' ', '2']
['0x31', '0x20', '0x41', '0x5c', '0x31', '0x5c', '0x6e', '0x42', '0x20', '0x32']
want to see:
hai! \1 <ops> $1 \' \x \\
getting:
hai! # <ops> $1 \' \x \
over escaped:
hai\!\ \1\ \<ops\>\ \$1\ \\'\ \x\ \\
could work:
hai! \1 <ops> $1 \' \x \\
前面使用
re.escape()
的答案转义太多,在替换和替换的字符串中会出现不需要的反斜杠
在Python中,似乎只有反斜杠需要在替换字符串中转义,因此这样就足够了:
replacement = replacement.replace("\\", "\\\\")
:
重新导入
x=r'hai!\1$1\'\x\\'
打印“想要查看:”
打印x
打印“获取:”
打印re.sub(“.(.”,x,“####”)
打印“溢出”:
打印re.sub(“(”,re.escape(x),“###”)
打印“可以工作:”
打印re.sub(“.(.”),x.replace(“\\”,“\\\”,“\\\”,“\\\”),“\\\”)
输出:
1 A\1
B 2
['1', ' ', 'A', '\\', '1', '\n', 'B', ' ', '2']
['0x31', '0x20', '0x41', '0x5c', '0x31', '0xa', '0x42', '0x20', '0x32']
1 A\1\nB 2
['1', ' ', 'A', '\\', '1', '\\', 'n', 'B', ' ', '2']
['0x31', '0x20', '0x41', '0x5c', '0x31', '0x5c', '0x6e', '0x42', '0x20', '0x32']
want to see:
hai! \1 <ops> $1 \' \x \\
getting:
hai! # <ops> $1 \' \x \
over escaped:
hai\!\ \1\ \<ops\>\ \$1\ \\'\ \x\ \\
could work:
hai! \1 <ops> $1 \' \x \\
要查看:
hai!\1$1\'\x\\
得到:
嗨!#$1\'\x\
过度逃逸:
海\!\\1\\\\\$1\\\\\\\\\\\\\\\\x\\
可以:
hai!\1$1\'\x\\
我无法控制给定给我的变量(包含替换字符串)中的内容。当然,我可以查找\1类型模式,并将其替换为\\1。但这既混乱又难看。这就是为什么有一种方法可以为您做到这一点:@max我完全更改了答案,也许我对那里发生的事情的思考对您有所帮助(至少我从你的问题中学到了很多。)明白了,谢谢。我想它也会弄乱“\n”,所以如果有人给我传递了一个字符串,他们想包含用“\n”表示的换行符,我就不走运了。但这没什么大不了的。@max:如果有人想要换行符,他们会传递一个单字节的换行符,而不是两字节的转义序列(当然,除非他们感到困惑)@Qtax你介意给出一个更正确的答案吗?我不确定我是否理解你的担忧。-1,不完全正确。这会逃逸太多,并且你会在替换的字符串中得到原始替换中没有的文字反斜杠。例如:@Duncan我更改了输出的格式,我错过了它解释了反斜杠斜杠,而不是仅仅打印它,这是你的问题,还是有另一个问题?好的,你是正确的,这里的re.escape是错误的选择,如果转义字符串用作正则表达式,这将是正确的,但是在替换字符串中,只需要转义\1
…所以理解这一点,我会稍微限制替换不仅仅是反斜杠,后面跟着这样的数字re.sub(r“\\(?=\d)”,r“\\\”,x)
(在您的示例中没有区别,同样不知道为什么,转义有时对我来说是个谜)re.sub(r“\\”,r