regex 修改一个反向引用.可以做到吗?

nhhxz33t  于 2023-02-05  发布在  其他
关注(0)|答案(4)|浏览(128)

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'

谢谢你的帮助。

rslzwgfq

rslzwgfq1#

来自文档:
如果 * repl * 是函数,则每次出现不重叠的 * pattern * 时都会调用该函数。该函数采用单个匹配对象参数,并返回替换字符串。例如:
并查看链接文档中包含的示例。

koaltpgm

koaltpgm2#

正如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()字符串方法,是因为您只想删除一个字符,而实际上并不需要使用正则表达式的全部功能。

p8h8hvxi

p8h8hvxi3#

“* 修改反向引用 *”需要重新措辞,因为您似乎混淆了概念。
replacement backreference是 * 字符串 * 中 * 字符的特殊 * 组合,它告诉正则表达式引擎引用在匹配操作期间检索到的某些特定捕获组值(也称为 * 子匹配 *)。
当使用r'\1'.upper()时,您试图将\1字符串变为大写,由于\1没有可大写的字母,因此您得到\1,并且此\1-未更改-作为字符串替换模式(的一部分)应用。
这就是您不能以这种方式修改捕获组值的原因。
这就是为什么必须使用可调用对象作为替换参数(参见Ignacio's answer):您需要将match对象传递给re.sub,以便能够处理 submatches(尽管您当然可以替换反向引用中的一两个字符,例如r'\g<12>'.replace('2','1'),以“混淆”\g<11>反向引用,但此操作没有什么意义)。

2mbi3lxu

2mbi3lxu4#

背景

  • Python 3.x
  • 使用re.sub执行正则表达式替换
  • 对字符串的一部分进行任意修改,而不修改整个字符串

问题场景

  • UserMattL/uu002matt1675257544希望将字符串的一部分与正则表达式匹配
  • 用户希望修改字符串的匹配部分

溶液

  • 此场景的一般解决方案已发布elsewhere in this thread
  • 这个答案给出了一个简单的例子,它基本上做了同样的事情,但是使用了python lambda,而不是声明一个独立的函数

示例

  • 用户具有与MSFT Windows文件路径规范匹配的字符串
  • 用户希望将驱动器号更改为小写,但不修改字符串的任何其他部分
  • regex在这里是合适的,因为驱动器号可以是任何字符,使得str.replace()不实用
import re
  ss7676demotest = 'D:/AlphaOne/BravoTwo'
  rx7676demotest = re.compile(r'^(\w):')
  ss7676demotest = re.sub(rx7676demotest, lambda obmatch: '{vjj}:'.format(vjj=obmatch.group(1).lower()), ss7676demotest,)
  print(ss7676demotest) ## d:/AlphaOne/BravoTwo

依据

  • python lambda允许用户最小化代码量

陷阱

  • 这个问题讨论的是修改反向引用,但这实际上不是这里要做的
  • 反向引用是一个正则表达式概念,用于指定与正则表达式的特定部分匹配的字符串子区域
  • 在这种情况下,我们希望指定其中一个匹配的子区域,这样我们就可以修改它而不影响字符串的任何其他部分
  • 我们使用python regex.match()对象(例如,本例中的obmatch.group(1))执行此操作
  • python lambda在不涉及大量逻辑的简单场景中是实用的,但并不总是有利的
  • 对于更复杂的转换,最好编写独立函数,而不是使用lambda
  • 以增强可读性
  • 使代码更易于维护
  • 请参见other answer in this thread了解替代的非lambda方法

相关问题