反转正则表达式替换

2 投票
2 回答
636 浏览
提问于 2025-04-16 09:55

给定一个用正则表达式表示的字符串转换,有没有简单的方法可以在Python中反向这个转换呢?

举个例子,假设有这样的转换:

def f(x): return re.sub('foo((:?bar)?)', r'\1', x)

它把 'foobar' 转换成 'bar',把 'foo' 转换成空字符串。我想得到:

def g(x): return re.sub('((:?bar)?)', r'foo\1', x)

这个转换是反向的,也就是说:

f(g(x)) == x

显然,并不是所有的正则表达式替换都是一一对应的,但我希望能找到一种方法,得到一个可能的输入值 g(x),这样就能从原来的替换中得到给定的输出 x

我为什么想这么做呢?因为我想根据解析 Apache 配置文件中的 AliasMatch 指令,生成任意文件系统路径的URL。

2 个回答

0

在这个例子中,实际上发生的事情是:

xy? -> $1
y?  -> x$1

我不太确定你想要什么——多给一些例子会更好——但我觉得这个通用公式可以扩展一下,至少可以涵盖更多简单的情况。

2

你的例子不太对;('(bar)?', 'foo$1') 其实并不是 ('foo(bar)?', '$1') 的反向操作。

如果你尝试一下(暂时不考虑分组替换):

import re
re.sub(r'(bar)?', 'foo', 'xyz')

你会得到 fooxfooyfoozfoo

这是因为 (bar)? 可以匹配空字符串,而空字符串在字符串的每个可能位置都存在。

我建议在遇到这种简单例子的问题时,可能需要换个思路来解决你真正想做的事情。

(我上面提到的分组是因为在Python中其实不太适用。如果你用 re.sub(r'(bar)?', r'foo\1', 'xyz'),如果 (bar)? 被跳过,就会出错。你可以用 ((bar)?) 来解决这个问题,这样外层的分组就不会被省略。不过这和你的问题关系不大。)

撰写回答