Python文件中的条件搜索和替换

Python文件中的条件搜索和替换,python,file-io,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 sa

当需要进行条件搜索和替换时,我有一个超过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)
Devanagari的脚本1不工作

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

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

预期产出:ं 替换为ङ् 像ग 跟随ं 那个सङ्गम

这里需要一个简单的正则表达式。像这样的

re.sub(r'a(?=[rmnu])',r'ā',"Hamro sano ghar holata.")
>>> 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.
编辑:

一些背景,首先:

这是一项更为艰巨的任务देवनागरी, 不是因为编码,而是因为组合字形的规则极其复杂,至少以拉丁文字的标准来说是如此。例如,我在Chrome上写下了这个答案,它仍然不能正确地为Devanāgarī组成Devanāgarī,它在错误的地方得到了“e”的变音符号——它对双音字母“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āra和virāma Hindi:halant。考虑到连字的工作方式,这可能会遗漏一些情况,但我已经将我的示例转换为使用前瞻,就像@Kabie的示例一样,这可能是一个更好的选择,以尽可能地缓解这种情况。

这里需要一个简单的正则表达式。像这样的

>>> 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.
编辑:

一些背景,首先:

这是一项更为艰巨的任务देवनागरी, 不是因为编码,而是因为组合字形的规则极其复杂,至少以拉丁文字的标准来说是如此。例如,我在Chrome上写下了这个答案,它仍然不能正确地为Devanāgarī组成Devanāgarī,它在错误的地方得到了“e”的变音符号——它对双音字母“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āra和virāma Hindi:halant。考虑到连字的工作方式,这可能会遗漏一些情况,但我已将我的示例切换为使用前瞻,就像@Kabie的示例一样,这可能是一个更好的选择,以尽可能减轻这种情况。

对于您的大文本文件,您应该复制原始文件,替换字符,并用更新的行写入一个新文件。您应该一次只读取一个块,而不是整个文件。虽然在一台现代计算机上,你可以一次就把整个10MB的内存消耗掉

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

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)
除非你有充分的理由,否则不要这样做。与计算机上可用的内存相比,面向行的版本易于理解,并且在文件较大时工作得更好

《深入Python》一书有一章解释正则表达式:

您希望读取Unicode并替换Unicode字符。您需要找出文件的本机编码,读入它,转换为Unicode,进行替换,然后以正确的编码写出它。也可以使用特殊的编解码器模块;codecs.open将为您提供自动转换的文件对象

以下是Python的Unicode操作文档:

因此,假设您要读取的文本文件是以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()

对于大型文本文件,应复制原始文件,替换字符,并使用更新的行编写新文件。你应该 一次只处理一块,而不是整个文件。虽然在一台现代计算机上,你可以一次就把整个10MB的内存消耗掉

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

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)
除非你有充分的理由,否则不要这样做。与计算机上可用的内存相比,面向行的版本易于理解,并且在文件较大时工作得更好

《深入Python》一书有一章解释正则表达式:

您希望读取Unicode并替换Unicode字符。您需要找出文件的本机编码,读入它,转换为Unicode,进行替换,然后以正确的编码写出它。也可以使用特殊的编解码器模块;codecs.open将为您提供自动转换的文件对象

以下是Python的Unicode操作文档:

因此,假设您要读取的文本文件是以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()

你能解释一下这是怎么回事吗?如何使用这个?>>>re.subr'a?=[rmnu]',r'ā',Hamro sano ghar holata。回溯最近的调用last:文件,第1行,在名称中错误:名称“re”未定义您应该在使用sub之前添加导入re。The?=。。。是一个前瞻性断言,它意味着。。。必须匹配,但不包括在替换中。其他答案使用常规匹配组…,这意味着匹配的位也被替换,因此如果您想保留它,您必须将其与\1一起放回。请您解释一下这是如何工作的?如何使用这个?>>>re.subr'a?=[rmnu]',r'ā',Hamro sano ghar holata。回溯最近的调用last:文件,第1行,在名称中错误:名称“re”未定义您应该在使用sub之前添加导入re。The?=。。。是一个前瞻性断言,它意味着。。。必须匹配,但不包括在替换中。其他答案使用常规匹配组…,这意味着匹配的位也被替换,因此如果要保留它,则必须使用\1.Hmm将其放回。我怀疑您在以Unicode格式读取文件时遇到问题。我已经用一些Unicode信息更新了我的答案。不,实际上你的主要问题是最后一行缺少一个“u”。。。但是,如果您正在使用Devanāgarī,请参阅我更新的答案以了解更多详细信息。user537488,当您使用它时,不要忘记接受其中一个答案。我认为西蒙的答案是最好的。我怀疑您在以Unicode格式读取文件时遇到问题。我已经用一些Unicode信息更新了我的答案。不,实际上你的主要问题是最后一行缺少一个“u”。。。但是,如果您正在使用Devanāgarī,请参阅我更新的答案以了解更多详细信息。user537488,当您使用它时,不要忘记接受其中一个答案。我认为simon的答案是最好的。File./WORKING.py,第11行代表openbig_File_10mb.txt中的第11行,mode=rb,encoding=utf-8:^SyntaxError:无效的语法对不起,我弄错了。现在修好了。我们希望使用codecs.open,而不是普通的内置open。内置没有编码=功能。使用codecs.open,如编辑后的answer.File./WORKING.py所示,第11行表示openbig_File_10mb.txt中的行,mode=rb,encoding=utf-8:^syntaxer错误:无效的语法对不起,我犯了一个错误。现在修好了。我们希望使用codecs.open,而不是普通的内置open。内置没有编码=功能。使用codecs.open,如编辑后的答案所示。