在文件中进行原地(多次)替换

3

我正在尝试对文件进行一些替换操作:

'\t' --> '◊'
 '⁞' --> '\t'

这个问题推荐以下步骤:

import fileinput

with fileinput.FileInput(filename, inplace=True, backup='.bak') as file:
    for line in file:
        line = line.replace('\t','◊')
        print(line.replace('⁞','\t'), end='')

我无法在那里发表评论,但当我运行这段代码时,会出现一个错误提示:

UnicodeDecodeError: 'charmap' codec can't decode byte 0x81 in position 10: character maps to <undefined>

我之前遇到过类似的错误,通过添加 encoding='utf-8' 来解决。 问题在于 fileinput.FileInput() 没有提供编码参数。 问题: 如何解决这个错误?
如果以下方法的速度与 上述解决方案 相当且能够进行原地替换,那么我将非常满意它。 我还尝试了以下方法:
replacements = {'\t':'◊', '⁞':'\t'}
with open(filename, encoding='utf-8') as inFile:
    contents = inFile.read()
with open(filename, mode='w', encoding='utf-8') as outFile:
    for i in replacements.keys():
        contents = contents.replace(i, replacements[i])
    outFile.write(contents)

这段代码的执行速度相对较快,但在内存使用方面非常贪婪。


对于UNIX用户,我需要一个能够执行以下操作的工具:

sed -i 's/\t/◊/g' 'file.csv'
sed -i 's/⁞/\t/g' 'file.csv'

这个结果变得相当缓慢。

1个回答

1
一般来说,使用FileInput时,您可以通过传递fileinput.hook_encoded作为openhook参数来指定所需的编码方式。
import fileinput

with fileinput.FileInput(filename, openhook=fileinput.hook_encoded('utf-8')) as file:
    # ...

然而,这与inplace=True不兼容。在这种情况下,您可以将文件视为二进制文件,并自己解码/编码字符串。对于读取,只需指定mode='rb'即可完成此操作,这将为您提供bytes而不是str行。对于写入,稍微复杂一些,因为print始终使用str,或将给定的输入转换为str,因此传递字节将无法按预期工作。但是,您可以直接将二进制数据写入sys.stdout,这将起作用:
import sys
import fileinput

filename = '...'
with fileinput.FileInput(filename, mode='rb', inplace=True, backup='.bak') as file:
    for line in file:
        line = line.decode('utf-8')
        line = line.replace('\t', '◊')
        line = line.replace('⁞', '\t')
        sys.stdout.buffer.write(line.encode('utf-8'))

而且它比我在帖子中使用的工作方法快了约2倍(在我的情况下)。使用的RAM数量可以忽略不计。这太棒了@jdehesa!谢谢! - Sandu Ursu

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