替换特定单词但不包括引号内的文本的正则表达式

3
我将尝试在字符串 s 中替换 Hello 为另一个单词,但只有当该单词不被引号 " " 或 ' ' 包围时。假设替换单词为 Matt,则输入如下:
s = 'Hello How Are you, "hey Hello", \'ney Hello\'. Hello I\'m great'

期望的输出:

s = 'Matt How are you, "hey Hello", \'ney Hello\'. Matt I\'m great '

我搜索了一些资料,发现这段代码,稍作修改之后,我成功替换了单引号中的文字,但是在双引号中并没有成功。

import re

def replace_method(match):

    if match.group(1) is None:
        return match.group()

    return match.group().replace("Hello", "Matt")

s = 'Hello How Are you, "hey Hello", \'ney Hello\'. Hello I\'m great'

output = re.sub(r"'[^']*'|([^']*)", replace_method, s)
print(output)

编辑:

谢谢你们的回答,但我错过了解释一些重要的东西(在成功执行代码后,我第一次注意到),“显然”,我不希望这个句子:

s = "Hellona, how are you"

变成

s = "Markna, how are you"

因此,正则表达式应包括要替换的单词周围没有数字字母

3个回答

1
替换回调函数看起来不错。
但是正则表达式需要改为:
r"('[^']*'|\"[^\"]*\")|\b[Hh]ello\b"
可读版本:
   (                             # (1 start)
        ' [^']* '
     |  
        " [^"]* "
   )                             # (1 end)
|  
   \b [Hh]ello \b

请注意,如果第一组匹配成功,则回调函数中的第一组检查必须为true。
我不是Python程序员,但应该像这样:
if match.group(1) :
    return match.group()
return "Matt"

嘿,谢谢你的回答,但是为什么正则表达式的末尾要加上 [Hh]ello? - Frederik
那么,我相信这就是你想匹配的内容。我错了吗? - user557597
是否也可以检查单词是否不被字母或数字包围,例如这个句子:“Hellona hey”,显然我不希望“Hellona”变成“Markna”。 - Frederik
哦,这不是原来的问题中提到的。请尝试发起一个新的问题。 - user557597
首先,我不小心给你的帖子点了踩。在你编辑之前,我无法点赞它。所以,我需要开始一个新的问题吗?我可以这样做,但请至少稍微编辑一下。这样我就可以点赞(或者至少取消我的踩)。你的if语句中缺少一个冒号 :) - Frederik
在Python条件语句的末尾添加了一个:,在正则表达式中使用了单词边界\b - user557597

1
import re


def replace_word(input, search, replace):
    def replace_method(match):
        if match.group(2) is None:
            return match.group()
        return match.group(2).replace(search, replace)
    expr = re.compile("('[^']*'|\"[^\"]*\")|({})".format(search))
    return re.sub(expr, replace_method, s)

s = 'Hello How Are you, "hey Hello", \'ney Hello\'. Hello I\'m great'

output = replace_word(s, "Hello", "Matt")
print(output)

你可以将单引号或双引号之间的所有内容匹配到第1组中(('[^']*'|\"[^\"]*\")),然后将你要查找的单词放在第2组中({}), 用search来格式化,最后用你想要的任何内容替换第2组。

你好,这只是对问题的补充。是否也可以检查单词是否没有被字母或数字包围,例如这个句子:“Hellona hey”,显然我不希望“Hellona”变成“Markna”。 - Frederik
使用该函数,您可以搜索正则表达式,它将格式化为编译后的表达式。例如,可以是“[\W]*hello[\W]*”,表示匹配被空格、标点符号或其他非字母数字字符包围的“hello”。 - Benoit Dufresne

-1

在这里,我们也许可以用以下方法解决这个问题:

([^'"]?)(Hello)([^'"])

我们可以用以下内容替换它:

enter image description here

正则表达式

如果您不想使用此表达式,可以在regex101.com上修改/更改您的表达式。

正则表达式电路

您还可以在jex.im中可视化您的表达式:

enter image description here

JavaScript演示

这个片段展示了我们可能有一个有效的表达式:

const regex = /([^'"]?)(Hello)([^'"])/gm;
const str = `Hello How Are you, "hey Hello", 'ney Hello'. Hello I'm great. "Hello' I'm great`;
const subst = `$1Matt$3`;

// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);

console.log('Substitution result: ', result);

Python 测试

# coding=utf8
# the above tag defines encoding for this document and is for Python 2.x compatibility

import re

regex = r"([^'\"]?)(Hello)([^'\"])"

test_str = "Hello How Are you, \"hey Hello\", 'ney Hello'. Hello I'm great. \"Hello' I'm great"

subst = "\1Matt\3"

# You can manually specify the number of replacements by changing the 4th argument
result = re.sub(regex, subst, test_str, 0, re.MULTILINE)

if result:
    print (result)

# Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.

为了排除 Hellona,我们可以添加单词边界:

([^'"]?)(\bHello\b)([^'"])

enter image description here

演示

const regex = /([^'"]?)(\bHello\b)([^'"])/gm;
const str = `Hello How Are you, "hey Hello", 'ney Hello'. Hello I'm great. "Hello' I'm great. Hellona how are you? `;
const subst = `$1Matt$3`;

// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);

console.log('Substitution result: ', result);


1
非常好,能否详细说明一下关于问题的最后一部分,即 s = "Hellona, how are you" 变成 s = "Markna, how are you"。如果 Hello 是 Hellone,它仍然会在您的代码中被替换为 Mark。 - Frederik

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