Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python re.sub:忽略替换字符串中的反向引用_Python_Regex_Python 3.x - Fatal编程技术网

Python re.sub:忽略替换字符串中的反向引用

Python re.sub:忽略替换字符串中的反向引用,python,regex,python-3.x,Python,Regex,Python 3.x,我想用字符串替换模式。字符串在变量中给定。当然,它可能包含“\1”,不应将其解释为反向引用,而应简单地解释为\1 我怎样才能做到这一点呢?由于评论的缘故,我对此思考了很久,并尝试了一下。帮助我提高了对逃跑的理解,所以我几乎完全改变了我的答案,以便对以后的读者有用 NullUserException只提供了一个简短的版本,我试着解释一下。多亏了Qtax和邓肯的批评性评论,这个答案现在有望是正确和有用的 反斜杠有一个特殊的含义,它是字符串中的转义字符,这意味着反斜杠和后面的字符构成了一个转义序列,当

我想用字符串替换模式。字符串在变量中给定。当然,它可能包含“\1”,不应将其解释为反向引用,而应简单地解释为\1


我怎样才能做到这一点呢?

由于评论的缘故,我对此思考了很久,并尝试了一下。帮助我提高了对逃跑的理解,所以我几乎完全改变了我的答案,以便对以后的读者有用

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