【问题标题】:Python - Modifying a backreference. Can it be done?Python - 修改反向引用。可以做到吗?
【发布时间】:2020-01-21 05:14:06
【问题描述】:

Python 新手,请原谅我的无知。我正在尝试修改正则表达式中的反向引用字符串。

例子:

>>>a_string
'fsa fad fdsa dsafasdf u.s.a. U.S.A. u.s.a fdas adfs.f fdsa f.afda'
>>> re.sub(r'(?<=\s)(([a-zA-Z]\.)+[a-zA-Z]\.{0,1})(?=\s)', '<acronym>'+re.sub(r'\.',r'',(r'\1').upper())+'</acronym>', a_string)
'fsa fad fdsa dsafasdf <acronym>u.s.a.</acronym> <acronym>U.S.A.</acronym> <acronym>u.s.a</acronym> fdas adfs.f fdsa f.afda'

而不是我想要的输出:

'fsa fad fdsa dsafasdf <acronym>USA</acronym> <acronym>USA</acronym> <acronym>USA</acronym> fdas adfs.f fdsa f.afda'

感谢您的帮助。

【问题讨论】:

    标签: python regex


    【解决方案1】:

    修改反向引用”需要重新措辞,因为您似乎混淆了这些概念。

    replacement backreference 是一个特殊的字符组合,位于 字符串 内,它告诉正则表达式引擎引用一些特定的捕获组值(又名 submatches) 在匹配操作期间检索到。

    当您使用r'\1'.upper() 时,您正在尝试将\1 字符串设为大写,并且由于\1 没有可大写的字母,因此您会得到\1,而这个\1 - 不变 - 是作为字符串替换模式的(部分)应用。

    这就是为什么您不能以这种方式修改捕获组值的原因。

    这就是为什么你必须use a callable as the replacement argument(参见Ignacio's answer):你需要将匹配对象传递给re.sub,以便能够操纵子匹配(尽管你可以当然在反向引用中替换一两个字符,例如,r'\g&lt;12&gt;'.replace('2','1') 以“混淆”\g&lt;11&gt; 反向引用,但这个操作没有什么意义。

    【讨论】:

    【解决方案2】:

    正如 Ignacio Vazquez-Abrams 所建议的,您可以通过将可调用函数传递给 re.sub() 来解决您的问题。我认为示例代码可以最好地解释它,所以你开始吧:

    import re
    
    s = "fsa fad fdsa dsafasdf u.s.a. U.S.A. u.s.a fdas adfs.f fdsa f.afda"
    
    s_pat = r'(?<=\s)(([a-zA-Z]\.)+[a-zA-Z]\.{0,1})(?=\s)'
    pat = re.compile(s_pat)
    
    def add_acronym_tag(match_object):
        s = match_object.group(0)
        s = s.replace('.', '').upper()
        return "<acronym>%s</acronym>" % s
    
    s = re.sub(pat, add_acronym_tag, s)
    print s
    

    以上打印:

    fsa fad fdsa dsafasdf <acronym>USA</acronym> <acronym>USA</acronym> <acronym>USA</acronym> fdas adfs.f fdsa f.afda
    

    所以你实际上并没有修改反向引用,因为字符串是不可变的。但这同样好:您可以编写一个函数来执行您想要的任何处理,然后返回您想要的任何内容,这就是re.sub() 将在最终结果中插入的内容。

    请注意,您可以在函数中使用正则表达式;我只是使用了.replace() 字符串方法,因为您只想删除单个字符,而您并不需要正则表达式的全部功能。

    【讨论】:

    • 谢谢,这很有帮助。但我仍然不确定为什么我最初的尝试没有奏效。难道 re.sub() 和 upper() 算作可调用函数吗?
    • 它们算作可调用函数。但是re.sub() 调用该函数并传递一个参数:一个“匹配对象”。 re.sub()str.upper() 不知道如何处理匹配对象。再看看我的功能;它做的第一件事是从匹配对象中提取字符串。因此,您需要编写一个调用re.sub()str.replace()str.upper() 的包装函数;包装器需要将匹配对象作为参数;并且包装器不需要接受任何其他参数来告诉它要做什么。
    【解决方案3】:

    来自the docs

    如果 repl 是一个函数,则每次出现 pattern 时都会调用它。该函数采用单个匹配对象参数,并返回替换字符串。例如:

    并查看链接文档中包含的示例。

    【讨论】:

    • 原谅我的无知,但我不知道这对我有什么帮助。该示例不使用反向引用。当我取出反向引用并说插入一个虚拟字符串时,它工作正常。问题在于对反向引用字符串的修改(我认为)。
    • 您是否尝试返回替换字符串?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多