【问题标题】:Python 2.7 - find and replace from text file, using dictionary, to new text filePython 2.7 - 使用字典从文本文件中查找和替换到新的文本文件
【发布时间】:2013-09-17 13:01:35
【问题描述】:

我是编程新手,过去几个月一直在业余时间学习python。我决定尝试创建一个小脚本,将美国拼写转换为文本文件中的英语拼写。

在过去的 5 个小时里,我一直在尝试各种事情,但最终想出了一些让我更接近目标的方法,但还没有完全实现!

#imported dictionary contains 1800 english:american spelling key:value pairs. 
from english_american_dictionary import dict


def replace_all(text, dict):
    for english, american in dict.iteritems():
        text = text.replace(american, english)
    return text


my_text = open('test_file.txt', 'r')

for line in my_text:
    new_line = replace_all(line, dict)
    output = open('output_test_file.txt', 'a')
    print >> output, new_line

output.close()

我确信有更好的方法来处理事情,但是对于这个脚本,我遇到了以下问题:

  • 在输出文件中,每行都写在隔行上,中间有一个换行符,但原始的 test_file.txt 没有这个。本页底部显示的 test_file.txt 的内容
  • 只有一行中美式拼写的第一个实例会转换为英语。
  • 我并不想以附加模式打开输出文件,但无法在此代码结构中找出“r”。

感谢这个热心的新手的任何帮助!

test_file.txt 的内容是:

I am sample file.
I contain an english spelling: colour.
3 american spellings on 1 line: color, analyze, utilize.
1 american spelling on 1 line: familiarize.

【问题讨论】:

  • 请注意:使用dict 作为变量的名称是一个非常糟糕的主意,因为它会隐藏内置字典类型的名称。如果您不小心,这可能会导致您的代码以令人困惑的方式中断。
  • 感谢您的提示,这里不会使用 'dict' 作为变量。

标签: python python-2.7


【解决方案1】:

您看到的额外空行是因为您正在使用print 写出一行末尾已经包含换行符的行。由于print 也编写了自己的换行符,因此您的输出变为双倍行距。一个简单的解决方法是改用outfile.write(new_line)

至于文件模式,问题在于您一遍又一遍地打开输出文件。你应该在开始时打开它一次。使用with 语句来处理打开的文件通常是个好主意,因为它们会在您完成后为您关闭它们。

我不理解您的其他问题,只是发生了一些替换。您的字典是否缺少'analyze''utilize' 的拼写?

我提出的一个建议是不要逐行替换。您可以使用file.read() 一次读取整个文件,然后将其作为一个单元进行处理。这可能会更快,因为它不需要在拼写字典中的项目上循环(只需一次,而不是每行一次):

with open('test_file.txt', 'r') as in_file:
    text = in_file.read()

with open('output_test_file.txt', 'w') as out_file:
    out_file.write(replace_all(text, spelling_dict))

编辑:

要使您的代码正确处理包含其他单词的单词(例如包含“tire”的“整个”),您可能需要放弃简单的str.replace 方法,转而使用正则表达式。

这是一个使用re.sub 的快速组合解决方案,给定一个从美式英语到英式英语的拼写变化词典(即按照您当前词典的相反顺序):

import re

#from english_american_dictionary import ame_to_bre_spellings
ame_to_bre_spellings = {'tire':'tyre', 'color':'colour', 'utilize':'utilise'}

def replacer_factory(spelling_dict):
    def replacer(match):
        word = match.group()
        return spelling_dict.get(word, word)
    return replacer

def ame_to_bre(text):
    pattern = r'\b\w+\b'  # this pattern matches whole words only
    replacer = replacer_factory(ame_to_bre_spellings)
    return re.sub(pattern, replacer, text)

def main():
    #with open('test_file.txt') as in_file:
    #    text = in_file.read()
    text = 'foo color, entire, utilize'

    #with open('output_test_file.txt', 'w') as out_file:
    #    out_file.write(ame_to_bre(text))
    print(ame_to_bre(text))

if __name__ == '__main__':
    main()

这种代码结构的一个好处是,如果您将字典以其他顺序传递给 replacer_factory 函数,您可以轻松地将英式英语拼写转换回美式英语拼写。

【讨论】:

  • 我很欣赏所有的答案,但我不得不通过@Blckknght 使用这个'file.read()',然后允许我以'w'模式打开out_file 太棒了!分析和利用确实转换为他们的英文版本,我只是脑筋急转弯。我用一个需要转换的较大文件尝试了这个脚本,其中一个问题是“整个”被转换为“整个”。这是因为“轮胎:轮胎”在字典中并且发生了部分匹配。有没有办法阻止这种情况,并一字不差地保持下去?
  • @Darren:好的,我的编辑完成了。我已经注释掉了依赖外部文件或模块的位,但是您可以插入(反转的)字典和数据文件而不是我使用的示例,它应该可以工作。
  • 替换函数作为参数传递给re.subre.sub 将为正则表达式模式匹配的每个单词调用一次。 match 参数将是由 re 代码创建的 MatchObject,用于描述匹配的内容。它与re.search 返回的对象相同。
  • @Darren:是的,re.sub 贯穿整个文本,将每个匹配项替换为您想要的任何内容。更复杂的是,第二个参数可以以多种方式工作:它可以是一个采用MatchObject 的函数(每次匹配都会调用它),也可以是一个字符串(可以包含反向引用)。
  • 这发生在re.sub 内部,这就是你看不到它的原因。对replacer 函数的引用被传递给re.sub,它的代码(可能是用C 编写的)在每次匹配时调用它,将match 对象作为参数传入。
【解决方案2】:

print 语句添加了自己的换行符,但您的行已经有了自己的换行符。您可以从new_line 中删除换行符,或者使用较低级别的

output.write(new_line)

相反(它会准确地写入您传递给它的内容)。

对于你的第二个问题,我认为我们需要一个实际的例子。 replace() 确实应该替换所有出现的地方。

>>> "abc abc abcd ab".replace("abc", "def")
'def def defd ab'

我不确定您的第三个问题在问什么。如果要替换输出文件,请执行

output = open('output_test_file.txt', 'w')

'w' 表示您正在打开文件进行写入。

【讨论】:

  • @ Tim Peters - 谢谢。我很困惑,'.replace' 方法实际上替换了所有实例。我的大脑被炸了!对于 'w' 或 'a' 的事情,我不得不使用 append 因为它在一个循环中,并且没有工作 'w'。只是想知道是否有办法使用'w',这样我就不必担心文件中是否已经有数据。我可以覆盖它。
【解决方案3】:

正如上面所有的好答案,我写了一个我认为更 Pythonic 的新版本,希望这有助于:

# imported dictionary contains 1800 english:american spelling key:value pairs.
mydict = {
    'color': 'colour',
}


def replace_all(text, mydict):
    for english, american in mydict.iteritems():
        text = text.replace(american, english)
    return text

try:
    with open('new_output.txt', 'w') as new_file:
        with open('test_file.txt', 'r') as f:
            for line in f:
                new_line = replace_all(line, mydict)
                new_file.write(new_line)
except:
    print "Can't open file!"

您还可以看到我之前提出的答案,其中包含许多最佳实践建议: Loading large file (25k entries) into dict is slow in Python?

这里有一些关于如何写python的其他技巧更多python:) http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html

祝你好运:)

【讨论】:

  • 感谢@shengy,这也是一个很好的答案,还有有用的链接,非常感谢:-)
猜你喜欢
  • 2020-12-20
  • 2011-06-12
  • 2019-07-30
  • 1970-01-01
  • 2013-05-27
  • 2017-02-06
  • 1970-01-01
  • 1970-01-01
  • 2014-07-05
相关资源
最近更新 更多