为re.sub替换参数转义Python正则表达式字符串? [复制]
Posted
技术标签:
【中文标题】为re.sub替换参数转义Python正则表达式字符串? [复制]【英文标题】:Python regex string escaping for re.sub replace argument? [duplicate] 【发布时间】:2020-02-06 08:22:59 【问题描述】:使用re
模块可以对替换模式使用转义。例如:
def my_replace(string, src, dst):
import re
return re.sub(re.escape(src), dst, string)
虽然这在大多数情况下都有效,但 dst
字符串可能包括 "\\9"
等。
这会导致问题:
\\1
、\\2
... 等在dst
中,文字将被解释为组。
使用re.escape(dst)
会导致.
更改为\.
。
有没有办法在不引入多余字符转义的情况下转义目的地?
示例用法:
>>> my_replace("My Foo", "Foo", "Bar")
'My Bar'
到目前为止,一切都很好。
>>> my_replace("My Foo", "Foo", "Bar\\Baz")
...
re.error: bad escape \B at position 3
这试图将\B
解释为具有特殊含义。
>>> my_replace("My Foo", "Foo", re.escape("Bar\\Baz"))
'My Bar\\Baz'
有效!
>>> my_replace("My Foo", "Foo", re.escape("Bar\\Baz."))
'My Bar\\Baz\\.'
.
在我们不想要的时候被转义。
虽然在这种情况下可以使用str.replace
,但关于目标字符串的问题仍然有用,因为有时我们可能想要使用re.sub
的其他功能,例如忽略大小写的能力。
【问题讨论】:
我不确定我是否理解这个问题 - 你能举一个示例字符串,src,dst 来演示它吗? 看起来你真正想要的是src.replace(r'\', r'\\')
,因为你似乎不想替换.
。
@metatoaster 你是说dst
吗? - 如果这避免了所有可能的解释,那么是的。
@ideasman42 是的。如果你只想要这个角色,这将是一种方式。如果您想从这个子集中进行多项修改,使用str.translate
可能更可取。最好的方法是创建一些测试用例(将它们添加到您的单元测试模块中)以形式化您要解决的问题。
@ideasman42 你有没有在不替换 dst 变量的情况下得到解决方案。在我的情况下,捕获组被视为没有 re.escape() 的文字
【参考方案1】:
如果您只是删除 re.escape
,您的代码可以正常工作,我不确定我们为什么会这样:
测试 1
import re
def my_replace(src, dst, string):
return re.sub(src, dst, string)
string = 'abbbbbb'
src = r'(ab)b+'
dst = r'\1z'
print(my_replace(src, dst, string))
输出 1
abz
测试 2
import re
def my_replace(src, dst, string):
return re.sub(src, dst, string)
string = re.escape("abbbbbbBar\\Baz")
src = r'(ab)b+'
dst = r'\1z'
print(my_replace(src, dst, string))
输出 2
abzBar\Baz
测试 3
import re
def my_replace(src, dst, string):
return re.sub(src, dst, string)
string = re.escape("abbbbbbBar\\Baz")
src = r'(ab)b+'
dst = r'\1' + re.escape('\\z')
print(my_replace(src, dst, string))
输出 3
ab\zBar\\Baz
测试 4
要构造dst
,我们必须首先知道在这种情况下我们是否会用任何捕获组(例如\1
)替换我们的字符串。我们不能re.escape
\1
,否则我们会将我们的字符串替换为\\1
,如果有捕获组,我们必须构造替换,然后将其附加到需要重新转义的任何其他部分。
import re
def my_replace(src, dst, string):
return re.sub(src, dst, string)
string = re.escape("abbbbbbBar\\Baz")
src = r'(ab)b+'
dst = r'\1' + re.escape('\9z')
print(my_replace(src, dst, string))
输出 4
ab\9zBar\\Baz
【讨论】:
需要转义,因为我无法控制参数。它们可能包含需要解释为文字的特殊字符。 测试2,正在解释目的地,尝试:dst = r'\9z'
【参考方案2】:
你可以诉诸拆分:
haystack = r"some text with stu\ff to replace"
needle = r"stu\ff"
replacement = r"foo.bar"
result = replacement.join(re.split(re.escape(needle), haystack))
print(result)
这也适用于干草堆的开头或结尾处的针。
【讨论】:
【参考方案3】:在这种情况下,只有反斜杠被解释为特殊字符,因此您可以在目标参数中使用简单的替换来代替 re.escape
。
def my_replace(string, src, dst):
import re
return re.sub(re.escape(src), dst.replace(r"\", r"\\"), string)
【讨论】:
以上是关于为re.sub替换参数转义Python正则表达式字符串? [复制]的主要内容,如果未能解决你的问题,请参考以下文章