为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正则表达式字符串? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Python正则替换字符串函数re.sub用法示例

re.sub的使用方法有哪些?

python re.sub详解

正则表达式re.sub替换不完整的问题现象及其根本原因

Python:re.sub()实现字符串替换

re.sub