字符串操作/正则表达式-查找和替换

3

我想要替换下面txt文件中每个句点.后面的单词:

line1
line2
field: [orders.cancelled,orders.delivered,orders.reached
orders.pickup,orders.time]
some line
some line

我有一个字典:

   d = {'cancelled':'cancelled_at', 'deliver':'xxx'}

我正在运行以下代码。然而,我只获得了部分匹配的结果,即:
我发现新文件包含以下单词:
field: [orders.cancelled_at, orders.xxxed ..........

这里的“delivered”一词是通过将前7个单词(deliver)替换并在末尾添加“ed”而形成的。我不确定为什么会这样。

with open('list.txt', 'r') as g:
    text = g.read()
    for k in d:
        before = f'.{k}'
        after = f'.{d[k]}
        #print(before)
        #print(after)
        text = text.replace(before, after)
        #print(text)

with open('new_list.txt', 'w') as w:
    w.write(text)

我也尝试了这个,结果一样。

import re

with open('list.txt', 'r') as f:
    text = f.read()
    for k in d:
        before = f'.{k}(?!=\w)'
        print(before)
        after = f'.{d[k]}'
        print(after)
        text = re.sub(before, after, text)

with open('new_list.txt', 'w') as w:
    w.write(text)

@WiktorStribiżew 我想我已经做了。而且,你认为\b在这里真的必要吗?因为只有当我在字典中有这个键时,匹配才会发生,所以我不太明白为什么我们要在这里使用\b。 - trillion
1
\b 单词边界是必要的,只有当字符串中存在整个单词时才匹配,因此 short\b 将匹配 short. 而不是 shorts - Wiktor Stribiżew
@HamzaShehzad 我会使用 :\s*\b(?!company\b)(\w+),然后代码将引用第一组,即 d[x.group(1)] - Wiktor Stribiżew
@WiktorStribiżew 我正在使用您的模式来匹配“公司”模式。但是,您能否解释一下为什么在这种情况下我必须引用组1而不仅仅是组()?此外,我的当前代码替换了模式1和模式2的所有单词,但它无法处理模式3。我不太确定您在这里所做的更改:changes = re.sub(pattern, lambda x: f'{x.group(1)}{d[x.group(2)]}' if x.group(1) else d[x.group()], line) 之前我们只有组()... 我不太确定这些组(组号和f'')是什么意思?https://ideone.com/9Dxg4M - trillion
第三种选择包含 (\w+),需要在你列出的一组单词之前有一个或多个单词字符,但是在示例中没有单词字符,你需要删除 (\w+)。关键错误是由于你的匹配从冒号和空格开始,你应该只捕获单词部分。尝试这段Python代码 - Wiktor Stribiżew
显示剩余19条评论
1个回答

1

您可以使用

import re

d = {'cancelled':'cancelled_at', 'deliver':'xxx'}
rx = re.compile(fr"(?<=\.)(?:{'|'.join(d)})\b")

with open('list.txt', 'r') as f:
    print( re.sub(rx, lambda x: d[x.group()], f.read()) )

请查看Python演示

代码生成的正则表达式如下

(?<=\.)(?:cancelled|deliver)\b

请查看regex演示。细节如下:

  • (?<=\.) - 正向后顾环体,匹配紧接着字面上的 .
  • (?:cancelled|deliver) - 两个备选项:cancelleddeliver
  • \b - 作为整个单词,\b 是一个单词边界。

lambda x: d[x.group()] 替换将匹配的单词替换为相应的字典键值。


嘿,你能解释一下我们什么时候使用 'f' 和 'fr' 吗?我看到你在 re.compile 中使用了 fr。如果你能解释一下它们之间的区别,我会非常感激的。 - trillion
1
@HamzaShehzad r 是原始字符串字面值前缀,用于定义一个字符串字面值,其中反斜杠不用于形成字符串转义序列(请阅读 Regular expression works on regex101.com, but not on prod 中的 BONUS 部分)。f 是一个 f-string 前缀,允许使用 变量插值(或变量扩展),即在字符串字面值中使用 {varname} 实际上将手动添加的字符串与变量连接起来(而不是使用 str.format)。 - Wiktor Stribiżew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接