Python - 修改反向引用。可以吗?

时间:2011-09-02 03:48:51

标签: python regex

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'

感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

来自the docs

  

如果 repl 是一个函数,则会为 pattern 的每次非重叠事件调用它。该函数接受单个匹配对象参数,并返回替换字符串。例如:

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

答案 1 :(得分: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()字符串方法,因为你只想摆脱一个字符,而你真的不需要正则表达式的全部功能。

答案 2 :(得分:1)

修改反向引用”需要重新措辞,因为您似乎对这些概念感到困惑。

replacement backreference是特殊的字符组合,位于 string 中,它告诉正则表达式引擎引用某些特定的捕获组值(又名子匹配)。

使用r'\1'.upper()时,您尝试使\1字符串大写,并且由于\1没有大写字母,因此得到\1,并且此\1-不变-用作字符串替换模式(的一部分)。

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

这就是为什么必须use a callable as the replacement argument(请参阅Ignacio's answer)的原因:您需要将match对象传递到re.sub才能操纵子匹配(尽管您当然可以在反引用中替换一个或两个字符,例如将r'\g<12>'.replace('2','1')替换为“模糊化” \g<11>的反向引用,但是此操作几乎没有意义。)