在 Python 中使用正则表达式查找和替换文件中的单词列表

Posted

技术标签:

【中文标题】在 Python 中使用正则表达式查找和替换文件中的单词列表【英文标题】:Finding and substituting a list of words in a file using regex in Python 【发布时间】:2015-01-05 10:11:00 【问题描述】:

我想将文件的内容打印到终端,并在此过程中突出显示在列表中找到的任何单词,而不修改原始文件。以下是尚未生效的代码示例:

    def highlight_story(self):
        """Print a line from a file and highlight words in a list."""

        the_file = open(self.filename, 'r')
        file_contents = the_file.read()

        for word in highlight_terms:
            regex = re.compile(
                  r'\b'      # Word boundary.
                + word       # Each item in the list.
                + r's0,1', # One optional 's' at the end.
                flags=re.IGNORECASE | re.VERBOSE)
            subst = '\033[1;41m' + r'\g<0>' + '\033[0m'
            result = re.sub(regex, subst, file_contents)

        print result
        the_file.close()

highlight_terms = [
    'dog',
    'hedgehog',
    'grue'
]

事实上,只有列表中的最后一项,无论它是什么或列表有多长,都会被突出显示。我假设每次替换都被执行,然后在下一次迭代开始时“忘记”。它看起来像这样:

Grues 已知会吃人类和非人类动物。在光线不足的地区,任何富裕的grue都认为狗和刺猬是美味佳肴。然而,狗可以通过在音阶中吠叫来吓唬 grue。另一方面,刺猬必须接受自己成为适合 grue 国王的热狗的命运。

但它应该是这样的:

Grues 已知会吃人类和非人类动物。在光线不足的地区,dogshedgehogs 被任何富裕的 grue 视为美味佳肴。 Dogs 可以吓跑 grue,但是,通过在音阶中吠叫。另一方面,hedgehog 必须接受自己成为适合 grue 国王的热狗的命运。

我怎样才能阻止其他替换丢失?

【问题讨论】:

【参考方案1】:

您可以将您的正则表达式修改为以下内容:

regex = re.compile(r'\b('+'|'.join(highlight_terms)+r')s?', flags=re.IGNORECASE | re.VERBOSE)  # note the ? instead of 0, 1. It has the same effect

那么,您将不需要for 循环。

此代码获取单词列表,然后将它们与| 连接在一起。所以如果你的清单是这样的:

a = ['cat', 'dog', 'mouse'];

正则表达式是:

\b(cat|dog|mouse)s?

【讨论】:

@ChristopherPerry,没问题。很高兴我能帮忙【参考方案2】:

您需要每次通过循环将file_contents重新分配给被替换的字符串,重新分配file_contents不会改变文件中的内容:

def highlight_story(self):
        """Print a line from a file and highlight words in a list."""

        the_file = open(self.filename, 'r')
        file_contents = the_file.read()
        output = ""
        for word in highlight_terms:
            regex = re.compile(
                  r'\b'      # Word boundary.
                + word       # Each item in the list.
                + r's0,1', # One optional 's' at the end.
                flags=re.IGNORECASE | re.VERBOSE)
            subst = '\033[1;41m' + r'\g<0>' + '\033[0m'
            file_contents  = re.sub(regex, subst, file_contents) # reassign to updatedvalue
        print file_contents
        the_file.close()

另外使用 with 打开文件是一种更好的方法,您可以在循环外复制字符串并在内部更新:

def highlight_story(self):
    """Print a line from a file and highlight words in a list."""
    with open(self.filename) as the_file:
        file_contents = the_file.read()
        output = file_contents # copy
        for word in highlight_terms:
            regex = re.compile(
                r'\b'  # Word boundary.
                + word  # Each item in the list.
                + r's0,1',  # One optional 's' at the end.
                flags=re.IGNORECASE | re.VERBOSE)
            subst = '\033[1;41m' + r'\g<0>' + '\033[0m'
            output = re.sub(regex, subst, output) # update copy
        print output
    the_file.close()

【讨论】:

【参考方案3】:

提供的正则表达式是正确的,但 for 循环是你出错的地方。

result = re.sub(regex, subst, file_contents)

此行将regex 中的subst 替换为file_content

在第二次迭代中,它再次在 file_content 中进行替换,正如您打算在 result 上进行的那样

如何纠正

结果 = 文件内容

for word in highlight_terms:
    regex = re.compile(
          r'\b'      # Word boundary.
        + word       # Each item in the list.
        + r's?\b', # One optional 's' at the end.
        flags=re.IGNORECASE | re.VERBOSE)
    print regex.pattern
    subst = '\033[1;41m' + r'\g<0>' + '\033[0m'
    result = re.sub(regex, subst, result) #change made here

 print result

【讨论】:

以上是关于在 Python 中使用正则表达式查找和替换文件中的单词列表的主要内容,如果未能解决你的问题,请参考以下文章

在多个文件中查找和替换正则表达式的最佳工具是啥?

在UltraEdit的查找和替换中使用正则表达式 (转)

使用正则表达式 python 查找和替换符号

使用Microsoft Word 2016中的正则表达式调整时间码

sublime text怎么使用高级正则查找替换

正则表达式查找函数的所有引用并将参数替换/添加到所有实例