条件搜索和替换文件Python

时间:2011-01-30 07:53:16

标签: python file-io

当需要进行条件搜索和替换时,我有一个超过10MB的大文本文件。如果“a”之后的字符是“r”或“m”或“n”或“u”,我想用“ā”替换文件中“a”的每个实例。

例如: 输入文件

Hamro sano ghar holata.

输出文件

Hāmro sāno ghār holata.

修改

谢谢你们,它似乎运作良好。但它似乎不适用于非拉丁字符,如印度语脚本: 拉丁字符的工作脚本:

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import re
input = "Hamro sano ghar holata."
regex = re.compile(ur'a([rmnu])')
print regex.sub(ur'ā\1', input)

Script1(对于梵文)没有工作

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import re
input ="संगम"
regex = re.compile(ur'ं([कखगघ])')
print regex.sub(r'ङ्\1', input)

Script2(添加了unicode东西)不工作

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import re
input =u"संगम"
regex = re.compile(ur'ं([कखगघ])', re.UNICODE)
print regex.sub(r'ङ्\1', input)

预期输出:ङ取代ङ्,因为הङ遵循सङ्गम

3 个答案:

答案 0 :(得分:3)

你需要一个简单的正则表达式。像这样的东西?

>>> import re
>>> input = "Hamro sano ghar holata."
>>> regex = re.compile(ur'a([rmnu])') # the part in parens is remembered
>>> print regex.sub(ur'ā\1', input) # replace by ā plus remembered part
Hāmro sāno ghār holata.

编辑:

一些背景,首先:

Devanāgarī(देवनागरी)这是一项 更艰巨的任务,不是因为编码,而是因为组合字形的规则非常复杂(至少,按照拉丁文字的标准)。我正在Chrome上写这个答案,例如,仍然不能正确地为“Devanāgarī”组成Devanāgarī(它在错误的地方得到'e'的变音标记 - 它确实与dipthong'ai'相同。)

这些字形由文本呈现引擎组合的方式称为“连字”,对于Devanāgarī,从技术角度来看,它们非常复杂。如果你添加संधि(saṃdhi)引入的更大的复杂性 - 再次,Chrome的渲染会在错误的地方获得代表anusvāra bindu ),那么你可以看到你在这里尝试做的事情很快就会很难非常

说了这么多,如果你的问题仅限于这个简单的案例,那么我认为它可以干净利落地完成。

>>> import re
>>> inputString = u"संगम"
>>> regex = re.compile(ur'\u0902(?=[कखगघ])')
>>> print regex.sub(ur'ङ\u094d', inputString)
सङ्गम

在正则表达式中,为了清楚起见,我用unicode转义值替换了anusvāravirāma(印地语: halant )。鉴于连字的工作方式,这可能会遗漏一些情况,但我已经将我的例子改为使用前瞻,就像在@ Kabie的例子中(这可能是一个更好的选择),尽可能地减轻这种情况。

答案 1 :(得分:2)

re.sub(r'a(?=[rmnu])',r'ā',"Hamro sano ghar holata.")

答案 2 :(得分:1)

对于大文本文件,您应复制原始文件,替换字符,并使用更新的行编写新文件。您应该一次只读取一个块,而不是整个文件。 (虽然在现代计算机上,你可以一次性啜饮整个10 MB。)

一种简单的方法是使用文件对象作为迭代器;这一次从文件中返回一行。

import re
pat = re.compile(ur'a([rmnu])') # pre-compile regex pattern for speed

f = open("corrected_file.txt", "wb")

for line in open("big_file_10mb.txt", "rb"):
    line = pat.sub(ur'ā\1', line)
    f.write(line)

f.close()

如果您想一次性覆盖整个文件,可以使用.read()方法函数:

f = open("big_file_10mb.txt", "rb")
s = f.read()  # read entire file contents
f.close()
s = pat.sub(ur'ā\1', s)  # replace over entire file contents
f = open("corrected_file.txt", "wb")
f.write(s)  # write entire file contents
f.close(s)

除非你有充分的理由,否则不要这样做。面向行的版本易于理解,并且当文件比计算机上的可用内存大时,效果会更好。

本书 Dive Into Python 有一章解释正则表达式:

http://diveintopython3.ep.io/regular-expressions.html

您想要读取Unicode并替换Unicode字符。您将需要找出文件的本机编码,读入它,转换为Unicode,执行替换,然后以正确的编码将其写出。或者您可以使用特殊的“编解码器”模块; codecs.open()将为您提供一个自动为您转换的文件对象。

这是Python的Unicode“how-to”文档:

http://docs.python.org/howto/unicode.html

因此,我们假设您要读取的文本文件以UTF-8编码。我认为这对你有用:

import codecs
import re

pat = re.compile(ur'a([rmnu])') # pre-compile regex pattern for speed

f = codecs.open("corrected_file.txt", mode="wb", encoding="utf-8")

for line in codecs.open("big_file_10mb.txt", mode="rb", encoding="utf-8"):
    line = pat.sub(ur'ā\1', line)
    f.write(line)

f.close()