【问题标题】:replacing all regex matches in single line替换单行中的所有正则表达式匹配
【发布时间】:2011-05-19 06:59:31
【问题描述】:

我有动态正则表达式,我事先不知道它有多少组 我想用 xml 标签替换所有匹配项

例子

re.sub("(this).*(string)","this is my string",'<markup>\anygroup</markup>')
>> "<markup>this</markup> is my <markup>string</markup>"

单行也可以吗?

【问题讨论】:

    标签: python regex


    【解决方案1】:

    对于您示例中的常量正则表达式,请执行

    re.sub("(this)(.*)(string)",
           r'<markup>\1</markup>\2<markup>\3</markup>',
           text)
    

    请注意,如果您不想丢失它,还需要将 .* 括在括号中。

    现在,如果您不知道正则表达式是什么样的,那就更难了,但应该是可行的。

    pattern = "(this)(.*)(string)"
    re.sub(pattern,
           lambda m: ''.join('<markup>%s</markup>' % s if n % 2 == 0
                             else s for n, s in enumerate(m.groups())),
           text)
    

    如果与您的模式匹配的第一件事不一定要标记,请改用它,第一组可以选择匹配一些应该单独保留的前缀文本:

    pattern = "()(this)(.*)(string)"
    re.sub(pattern,
           lambda m: ''.join('<markup>%s</markup>' % s if n % 2 == 1
                             else s for n, s in enumerate(m.groups())),
           text)
    

    你明白了。

    如果您的正则表达式很复杂,并且您不确定是否可以将所有内容都作为组的一部分,其中只有每隔一个组需要标记,您可能会使用更复杂的函数做一些更聪明的事情:

    pattern = "(this).*(string)"
    def replacement(m):
        s = m.group()
        n_groups = len(m.groups())
        # assume groups do not overlap and are listed left-to-right
        for i in range(n_groups, 0, -1):
            lo, hi = m.span(i)
            s = s[:lo] + '<markup>' + s[lo:hi] + '</markup>' + s[hi:]
        return s
    re.sub(pattern, replacement, text)
    

    如果您需要处理重叠组,则只能靠自己,但应该可行。

    【讨论】:

    【解决方案2】:

    是的,这可以在一行中完成。

    >>> re.sub(r"\b(this|string)\b", r"<markup>\1</markup>", "this is my string")
    '<markup>this</markup> is my <markup>string</markup>'
    

    \b 确保只匹配完整的单词。

    因此,如果您有一个需要标记的单词列表,您可以执行以下操作:

    >>> mywords = ["this", "string", "words"]
    >>> myre = r"\b(" + "|".join(mywords) + r")\b"
    >>> re.sub(myre, r"<markup>\1</markup>", "this is my string with many words!")
    '<markup>this</markup> is my <markup>string</markup> with many <markup>words</markup>!'
    

    【讨论】:

      【解决方案3】:

      re.sub() 将替换它可以替换的所有内容。如果您将repl 的函数传递给它,那么您可以做得更多。

      【讨论】:

      • 我希望我的匹配出现在 \1|\2|\3.. 之间
      • 这就是我正在寻找的正确答案!
      猜你喜欢
      • 2016-11-04
      • 1970-01-01
      • 1970-01-01
      • 2012-05-16
      • 1970-01-01
      • 1970-01-01
      • 2013-12-06
      • 2021-04-10
      • 1970-01-01
      相关资源
      最近更新 更多