繁体   English   中英

python搜索/替换类似sed的正则表达式

[英]python search/replace regex with sed-like expression

我想在Python中实现类似sed的搜索和替换。

现在显然,Python具有re模块:

import re
re.sub("([A-Z]+)", r"\1-\1", "123 ABC 456")

但是,我想在单个字符串中指定搜索/替换操作,例如在sed中(暂时不留任何转义问题):

s/([A-Z]+)/\1-\1/g

我之所以喜欢这种语法,是因为实际的搜索和替换规范由用户提供,并且我认为对于用户而言,指定单个搜索/替换字符串而不是模式模板都更为简单。

更新资料

对sed的s (搜索/替换)命令感兴趣,因为它用于单行(无特殊扩展名)。 用例实际上是允许用户为主机名提供字符串转换(带有组)。

有任何想法吗?

我最初的想法只是将它分割为/并将其作为args传递给re.sub

事实证明这是相当复杂的,并且我敢肯定它不是防弹的,所以我以此为起点。

问题是,如果我们要处理斜杠,例如用反斜杠替换斜杠,该怎么办。 然后sed表达式将是

's/\\/\//g'

我必须用没有反斜杠的斜杠来分割它

_, pattern, repl, options = re.split(r'(?<!\\)/', sed)

为了使其更加复杂,可以在shash之前加上两个反斜杠,因此:

_, pattern, repl, options = re.split(r'(?<![^\\]\\)/', sed)

re.sub看起来像

re.sub(pattern, repl, s, count='g' not in options)

Ups,不,在Python中,不必转义斜杠,因此:

re.sub(pattern, re.sub(r'\\/', '/', repl), s, count='g' not in options)

>>> import re
>>> s = r'\some\windows\path'
>>> sed = r's/\\/\//g'
>>> _, pattern, repl, options = re.split(r'(?<![^\\]\\)/', sed)
>>> re.sub(pattern, re.sub(r'\\/', '/', repl), s, count='g' not in options)
'/some/windows/path'

Python的re不支持此语法。 如果要使用这样的工具,则需要开发自己的API,因此必须解析类似sed的命令并执行相应的re函数。

您可以编写一个函数,给定类似于sed的s/命令,对其进行解析,然后返回相应的re函数。 然后可以在任何字符串上使用此返回的函数。

def run_sed_sub(command):
    regex = re.compile(r"(?!=\\)/")    # split on unescaped slashes
    parts = regex.split(command)
    if parts[0] != 's':
        raise ValueError("Not a sub command")

    regex = re.compile(parts[1])
    return lambda s: regex.sub(parts[2], s)

>>> func = run_sed_sub(r"s/Hello/Goodbye/g")
>>> print(func("Hello, world!"))
Goodbye, world!

>>> func = run_sed_sub(r"s/([A-Z]+)/\1-\1/g")
>>> print(func("123 ABC 456"))
123 ABC-ABC 456

有些前卫的情况可能会很痛苦,例如换行,但想法就在这里。 您可能还想用普通斜杠替换以sed方式转义的斜杠,因此, parts = [re.sub(r"\\\\/", "/", p) for p in parts]应该可以解决问题。

我也不知道最后如何处理这些标志,但是我想如果知道期望的行为并不难。

尽管如此,我还要补充一点,实现这种工具的样板可能比仅仅学习Python的re还要重要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM