我想用字符串替换模式。字符串以变量形式给出。它当然可能包含'\ 1',它不应该被解释为反向引用 - 而只是作为\ 1。
我怎样才能做到这一点?
答案 0 :(得分:6)
使用re.escape()
的上一个答案会逃避太多,并且在替换和替换的字符串中会出现不需要的反斜杠。
似乎在Python中只有反斜杠需要在替换字符串中转义,因此这样的事情就足够了:
replacement = replacement.replace("\\", "\\\\")
import re
x = r'hai! \1 <ops> $1 \' \x \\'
print "want to see: "
print x
print "getting: "
print re.sub(".(.).", x, "###")
print "over escaped: "
print re.sub(".(.).", re.escape(x), "###")
print "could work: "
print re.sub(".(.).", x.replace("\\", "\\\\"), "###")
输出:
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 \\
答案 1 :(得分:5)
由于评论,我想了很久,并试了一下。帮助我增加了对逃避的理解,所以我几乎完全改变了我的答案,它可能对以后的读者有用。
NullUserException为您提供了简短的版本,我尝试再解释一下。感谢Qtax和Duncan的批评性评论,希望这个答案现在正确且有用。
反斜杠具有特殊含义,它是字符串中的转义字符,这意味着反斜杠和后续字符形成一个转义序列,当使用字符串完成某些操作时,转义为其他内容。这个“完成的东西”已经是字符串的创建。因此,如果你想在字面上使用\
,你需要逃避它。这个转义字符就是反斜杠本身。
首先要开始一些例子,以便更好地了解会发生什么。我还在字符串中打印字符的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
的替换字符串。
所以新情况:
包含转义序列的原始字符串应该用作re.sub
的替换字符串。 re.sub
也会处理转义序列,但与之前的处理有一个小但重要的区别:\n
仍然会转换为0x0a
换行符,但转换为{{ 1}}现在已经改变了!它将被\1
中正则表达式的捕获组1的内容替换。
re.sub
结果是
s = r"A\1\nB"
print re.sub(r"(Replace)" ,s , "1 Replace 2")
1 AReplace
B 2
已替换为捕获组的内容,\1
替换为LineFeed字符。
重要的是,你必须了解这种行为,现在你有两种可能性(我不会判断哪一种是正确的)
创作者不确定字符串行为,如果他输入\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']
。在这种情况下逃避所有
\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]