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

时间:2014-11-08 19:34:02

标签: python regex python-2.7

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

    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's{0,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 吃人类和非人类动物。在光线不足的地区 hedgehogs 被任何富裕的 grue 视为美味佳肴。然而, Dogs 可以通过在音阶中吠叫来吓跑 grue 。另一方面, hedgehog 必须简单地让自己屈服于成为适合 grue 国王的热狗的命运。

如何阻止其他替换丢失?

3 个答案:

答案 0 :(得分:5)

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

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?

答案 1 :(得分:4)

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

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

此行将regex替换为subst中的file_content

在第二次迭代中,它再次在file_content中进行替换,您希望在result上进行替换

如何纠正

result = file_contents

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

答案 2 :(得分: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's{0,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's{0,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()