【问题标题】:How to replace only part of the match with python re.sub如何用 python re.sub 仅替换部分匹配项
【发布时间】:2011-02-15 08:45:33
【问题描述】:

我需要用一个reg表达式匹配两种情况并进行替换

'long.file.name.jpg' -> 'long.file.name_suff.jpg'

'long.file.name_a.jpg' -> 'long.file.name_suff.jpg'

我正在尝试执行以下操作

re.sub('(\_a)?\.[^\.]*$' , '_suff.',"long.file.name.jpg")

但这是删除扩展名“.jpg”,我得到了

long.file.name_suff。而不是 long.file.name_suff.jpg 我知道这是因为 [^.]*$ 部分,但我不能排除它,因为 我必须找到最后一次出现的“_a”来替换或最后一次出现“。”

有没有办法只替换部分匹配项?

【问题讨论】:

  • 你为什么要转义下划线(\\_a)?

标签: python regex


【解决方案1】:
print(re.sub('name(_a)?','name_suff','long.file.name_a.jpg'))
# long.file.name_suff.jpg

print(re.sub('name(_a)?','name_suff','long.file.name.jpg'))
# long.file.name_suff.jpg

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
【解决方案2】:
 re.sub(r'(?:_a)?\.([^.]*)$', r'_suff.\1', "long.file.name.jpg")

?: 启动一个非匹配组 (SO answer),因此 (?:_a) 匹配 _a 但不枚举它,以下问号使其可选。

所以在英语中,这就是说,匹配跟随(或不跟随)模式_a的结尾.<anything>

另一种方法是使用 lookbehind (see here)。提到这一点是因为它们非常有用,但我做了 15 年的 RE 都不知道它们

【讨论】:

    【解决方案3】:

    您可以通过排除更换部件来做到这一点。我的意思是,你可以对 regex 模块说; “与此模式匹配,但替换其中的一部分”。

    re.sub(r'(?<=long.file.name)(\_a)?(?=\.([^\.]*)$)' , r'_suff',"long.file.name.jpg")
    >>> 'long.file.name_suff.jpg'
    

    long.file.name.jpg 部分用于匹配,但它们排除在替换之外。

    【讨论】:

    • 后视?&lt;= 只允许固定宽度的模式。如果你有,这是一个不错的选择。
    【解决方案4】:

    只需将扩展的表达式放入一个组中,捕获它并在替换中引用匹配项:

    re.sub(r'(?:_a)?(\.[^\.]*)$' , r'_suff\1',"long.file.name.jpg")
    

    此外,使用非捕获组(?:…) 将防止重新存储大量不需要的信息。

    【讨论】:

      【解决方案5】:

      在要保留的部分周围放置一个捕获组,然后在替换文本中包含对该捕获组的引用。

      re.sub(r'(\_a)?\.([^\.]*)$' , r'_suff.\2',"long.file.name.jpg")
      

      【讨论】:

      • @Amber:我从您的回答中推断,与 str.replace() 不同,我们不能在原始字符串中使用变量 a);或 b) 作为 re.sub 的参数;或 c) 两者。 a) 有道理(我认为),但我不确定 b)。不过,似乎我们可以为正则表达式所经过的字符串使用变量名。你愿意解释一下吗?谢谢。
      • 捕获和引用它的部分是什么?
      猜你喜欢
      • 2012-08-15
      • 2022-12-04
      • 2015-12-18
      • 2014-06-26
      相关资源
      最近更新 更多