python - 如何在 python 中捕获文本并同时替换它?

标签 python regex

我的目标是查看一个字符串并提取以下形式的名称:"$name$"(没有空格)。我想提取名称(不带“$”),然后用数字替换名称。因此,例如,我想按照以下方式做一些事情:

raw_string = "Hello $tim$ my name is $sam$ I'll call you $tim$"
m = re.compile(r"\$(\S+)\$")

以这样的方式结束

names          # { "tim": 0, "sam": 1 }
parsed_string  # "Hello $0$ my name is $1$ I'll call you $0$"

有没有更好或更有效的方法来做到这一点,而不是使用 re.search()re.findall() 分两步完成,然后 re.sub()?

您可以在适当的位置对匹配对象执行子操作吗?

或者只进行两次遍历以找到所有匹配项然后替换它们会更有效吗?

抱歉,如果这是一个重复的问题,我没有找到任何解决方案。感谢您的帮助!

最佳答案

结合匹配和替换

据我所知(即使在 PyPi 正则表达式库中)没有允许您同时捕获和替换的函数。你所说的大多数 pythonic 是什么意思,没有人知道(它是基于意见的),但是,我认为这是一种在 python 中完成此操作的干净方法,而无需同时进行查找(re .searchre.findall) 并替换 (re.sub)。

条件替换

没有回调就无法进行条件替换,因为您要用不同的值替换文本。是的,您可以创建一个 for 循环并找到 \$([^$]+)\$ 的每个实例,但是您会遇到一个新问题:您不能用相同的数字而不使用额外的逻辑($tim$ 的第二个实例将变为 $2$ 而不是 $0)。

那么有人可能会想到反向引用。由于反向引用仅在 文本被捕获后才起作用,因此您不能在没有首先定位的情况下将 $tim$ 的多个实例替换为 $0$他们每个人都在字符串中。反向引用将不起作用,因为它们引用的组在使用反向引用之前必须具有匹配项,否则它将设置为空字符串:\1(.) 仅匹配一个字符,因为 \1 是对当前设置为不匹配的捕获组 1 的反向引用;而 (.)\1 将匹配两个字符。

在这一点上,我们可能希望默认返回到搜索和替换的两个方法调用。但是有一个巧妙的小方法可以实现这一点:回调。


使用回调

您可以通过使用 re.sub 中的回调来完成您想要做的事情。您仍然需要为重复实例添加逻辑,但这比调用两种不同的匹配和替换方法要好得多。

import re

names = {}
def repl(m):
    n = m.group(1)
    if n not in names:
        names[n]=len(names)
    return "$"+str(names[n])+"$"

s = "Hello $tim$ my name is $sam$ I'll call you $tim$"
r = re.compile(r'\$([^$]+)\$')
s = re.sub(r,repl,s)

print(names)
print(s)

结果:

{'tim': 0, 'sam': 1}
Hello $0$ my name is $1$ I'll call you $0$

关于python - 如何在 python 中捕获文本并同时替换它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59163535/

相关文章:

python - ebook-convert 吐出 python 错误?有人能理解错误吗?

python - python 中的循环优化

python - 为什么 pandas 显示 "?"而不是 NaN

python - EOL 字符串文字使用 webdriver selenium 创建保存位置

regex - Grep/Sed 每次出现换行符后跟 bash 中的字符串

jquery - 使用Jquery和正则表达式更改部分HREF

javascript - 使用 JavaScript (RegExp) 转换 HTML 实体

python - 调用类的方法,类名是一个变量

regex - Apache FilesNotMatch 正则表达式?

javascript - 如何使用正则表达式(JS)查找html的每个 <a href ="">