max*_*max 5 python regex python-3.x
我想用字符串替换模式.字符串以变量形式给出.它当然可能包含'\ 1',它不应该被解释为反向引用 - 而只是作为\ 1.
我怎样才能做到这一点?
上一个使用的答案re.escape()会逃避太多,你会在替换和替换的字符串中得到不合需要的反斜杠.
看起来在Python中只有反斜杠需要在替换字符串中转义,因此这样的事情就足够了:
replacement = replacement.replace("\\", "\\\\")
Run Code Online (Sandbox Code Playgroud)
示例:
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("\\", "\\\\"), "###")
Run Code Online (Sandbox Code Playgroud)
输出:
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 \\
Run Code Online (Sandbox Code Playgroud)
由于评论,我想了很长一段时间,并试了一下.帮助我增加了对逃避的理解,所以我几乎完全改变了我的答案,它可能对以后的读者有用.
NullUserException为您提供了简短的版本,我试着再解释一下.由于对Qtax和Duncan的批评性评论,这个答案现在是正确和有用的.
反斜杠具有特殊含义,它是字符串中的转义字符,这意味着反斜杠和后面的字符形成一个转义序列,当使用字符串完成某些操作时转换为其他内容.这个"完成的东西"已经是字符串的创建.因此,如果你想使用\字面意思,你需要逃避它.这个转义字符就是反斜杠本身.
因此,开始一些例子,以便更好地了解会发生什么.我另外打印字符串中字符的ASCII码,以期增加对所发生情况的可理解性.
s = "A\1\nB"
print s
print [x for x in s]
print [hex(ord(x)) for x in s]
Run Code Online (Sandbox Code Playgroud)
正在印刷
A
B
['A', '\x01', '\n', 'B']
['0x41', '0x1', '0xa', '0x42']
Run Code Online (Sandbox Code Playgroud)
因此,当我键入\并1在代码中,s不包含这两个字符时,它包含ASCII字符0x01,即"标题的开头".同样的\n,它转换为0x0aLinefeed角色.
由于并不总是需要此行为,因此可以使用原始字符串,其中将忽略转义序列.
s = r"A\1\nB"
print s
print [x for x in s]
print [hex(ord(x)) for x in s]
Run Code Online (Sandbox Code Playgroud)
我刚刚r在字符串之前添加了结果,结果就是现在
A\1\nB
['A', '\\', '1', '\\', 'n', 'B']
['0x41', '0x5c', '0x31', '0x5c', '0x6e', '0x42']
Run Code Online (Sandbox Code Playgroud)
所有字符都是在我输入时打印的.
这就是我们的情况.现在还有下一件事.
可能存在这样的情况:应该将字符串传递给正则表达式,因此在正则表达式中具有特殊含义的每个字符(例如+*$ [.)都需要转义,因此有一个特殊的函数re.escape可以执行这个工作.
但是对于这个问题,这是一个错误的函数,因为字符串不应该在正则表达式中使用,而是作为替换字符串re.sub.
所以新情况:
包含转义序列的原始字符串应该用作替换字符串re.sub.re.sub也将处理转义序列,但与之前的处理有一个小但重要的区别: \n仍然转换为0x0a换行符,但转换\1现在已经改变了!它将被正则表达式的捕获组1的内容替换re.sub.
s = r"A\1\nB"
print re.sub(r"(Replace)" ,s , "1 Replace 2")
Run Code Online (Sandbox Code Playgroud)
结果是
1 AReplace
B 2
Run Code Online (Sandbox Code Playgroud)
该\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
Run Code Online (Sandbox Code Playgroud)
输出:
1 A\1
B 2
['1', ' ', 'A', '\\', '1', '\n', 'B', ' ', '2']
['0x31', '0x20', '0x41', '0x5c', '0x31', '0xa', '0x42', '0x20', '0x32']
Run Code Online (Sandbox Code Playgroud)创作者确切地知道他在做什么,如果他想要换行,他就会输入\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]
Run Code Online (Sandbox Code Playgroud)
输出:
1 A\1\nB 2
['1', ' ', 'A', '\\', '1', '\\', 'n', 'B', ' ', '2']
['0x31', '0x20', '0x41', '0x5c', '0x31', '0x5c', '0x6e', '0x42', '0x20', '0x32']
Run Code Online (Sandbox Code Playgroud)