多行 UTF8 正则表达式替换大文件
Multiline UTF8 regex replace on a large file
我有大型 UTF8
文本文件,其中包含不需要的 linebreaks:not 所有换行符都不好,只有其中一些,即那些中断句子的。我想一个一个地浏览文件,加入行并写入新的输出文件。我想用Python 3
(教育原因!)。
我在小文件上测试了下面的代码。它几乎可以工作。但是我有三个问题。
我在替换项附近的输出文件中得到乱码。
对于较大的文件(大约 100Mb)是否有更好的做法?我大概无法使用 this 等逐行解决方案。我认为使用 MMAP
有助于阅读部分,但写作部分呢?
- 有没有比我用过更方便的处理UTF8的方法。附加
.encode()
和 .decode()
很烦人,我似乎是随机添加它们。我不能以某种方式告诉代码:"everything is in UTF8"
(我正在通过一个天真的正则表达式定位不需要的换行符。我知道它可能会更好,但这不是我目前关心的问题。)
#!/opt/local/bin/python3.6
from mmap import mmap, ACCESS_READ
from re import compile,MULTILINE
q=compile('([a-z])\n+([a-z])'.encode(),MULTILINE)
with open("infile", 'rb', 0) as file, open("outfile", "wb") as outfile, \
mmap(file.fileno(), 0, access=ACCESS_READ) as s:
outfile.write(q.sub(" ".encode(),s))
在 python3 中实现目标的一种非常简单的方法是
with open(r'c:\temp\infile.txt', 'r', encoding='utf-8') as f1, \
open(r'c:\temp\outfile.txt', "w", encoding='utf-8' ) as o1:
for line in f1.read():
o1.write(line.strip('\n'))
不需要正则表达式。对于 100 MB 的文件,逐行方法实际上非常有效。
测试于 windows 7
以下对我有用(在 Windows 上),尽管 read()
调用可能会否定您认为使用 mmap
获得的任何好处。 "rubbish characters" 可能是因为您忘记了大多数正则表达式模式字符串上的 r
字符串前缀(通常需要)。顺便说一句,您的正则表达式模式似乎有效。
from mmap import mmap, ACCESS_READ
from re import compile, MULTILINE
q = compile(r'([a-z])\r\n+([a-z])', MULTILINE)
with open("regex_subst.txt", 'r', encoding='utf-8') as file, \
open("outfile.txt", "w", encoding='utf-8') as outfile, \
mmap(file.fileno(), 0, access=ACCESS_READ) as s:
outfile.write( q.sub(r" ", s.read().decode()) )
这里有一个略有不同的方法,它不调用 read()
但仍然有效。 re
模块可用于字符串 或 字节,只要您传递给它的值始终是一种类型或另一种类型。
在下面的代码中,正则表达式模式字符串都以字母 r
和 b
为前缀,因此使它们成为 byte
模式而不是 str
模式。这使得 q.sub(br" ", s)
不会生成 TypeError: cannot use a string pattern on a bytes-like object
错误。但是,在将结果写入 UTF8 编码的输出文件之前,必须首先对替换的字节字符串结果进行显式解码,如图所示。
from mmap import mmap, ACCESS_READ
from re import compile, MULTILINE
q = compile(br'([a-z])\r\n+([a-z])', MULTILINE)
with open("regex_subst.txt", 'r', encoding='utf-8') as file, \
open("outfile.txt", "w", encoding='utf-8') as outfile, \
mmap(file.fileno(), 0, access=ACCESS_READ) as s:
outfile.write( q.sub(br" ", s).decode() )
我有大型 UTF8
文本文件,其中包含不需要的 linebreaks:not 所有换行符都不好,只有其中一些,即那些中断句子的。我想一个一个地浏览文件,加入行并写入新的输出文件。我想用Python 3
(教育原因!)。
我在小文件上测试了下面的代码。它几乎可以工作。但是我有三个问题。
我在替换项附近的输出文件中得到乱码。
对于较大的文件(大约 100Mb)是否有更好的做法?我大概无法使用 this 等逐行解决方案。我认为使用
MMAP
有助于阅读部分,但写作部分呢?- 有没有比我用过更方便的处理UTF8的方法。附加
.encode()
和.decode()
很烦人,我似乎是随机添加它们。我不能以某种方式告诉代码:"everything is in UTF8"
(我正在通过一个天真的正则表达式定位不需要的换行符。我知道它可能会更好,但这不是我目前关心的问题。)
#!/opt/local/bin/python3.6
from mmap import mmap, ACCESS_READ
from re import compile,MULTILINE
q=compile('([a-z])\n+([a-z])'.encode(),MULTILINE)
with open("infile", 'rb', 0) as file, open("outfile", "wb") as outfile, \
mmap(file.fileno(), 0, access=ACCESS_READ) as s:
outfile.write(q.sub(" ".encode(),s))
在 python3 中实现目标的一种非常简单的方法是
with open(r'c:\temp\infile.txt', 'r', encoding='utf-8') as f1, \
open(r'c:\temp\outfile.txt', "w", encoding='utf-8' ) as o1:
for line in f1.read():
o1.write(line.strip('\n'))
不需要正则表达式。对于 100 MB 的文件,逐行方法实际上非常有效。
测试于 windows 7
以下对我有用(在 Windows 上),尽管 read()
调用可能会否定您认为使用 mmap
获得的任何好处。 "rubbish characters" 可能是因为您忘记了大多数正则表达式模式字符串上的 r
字符串前缀(通常需要)。顺便说一句,您的正则表达式模式似乎有效。
from mmap import mmap, ACCESS_READ
from re import compile, MULTILINE
q = compile(r'([a-z])\r\n+([a-z])', MULTILINE)
with open("regex_subst.txt", 'r', encoding='utf-8') as file, \
open("outfile.txt", "w", encoding='utf-8') as outfile, \
mmap(file.fileno(), 0, access=ACCESS_READ) as s:
outfile.write( q.sub(r" ", s.read().decode()) )
这里有一个略有不同的方法,它不调用 read()
但仍然有效。 re
模块可用于字符串 或 字节,只要您传递给它的值始终是一种类型或另一种类型。
在下面的代码中,正则表达式模式字符串都以字母 r
和 b
为前缀,因此使它们成为 byte
模式而不是 str
模式。这使得 q.sub(br" ", s)
不会生成 TypeError: cannot use a string pattern on a bytes-like object
错误。但是,在将结果写入 UTF8 编码的输出文件之前,必须首先对替换的字节字符串结果进行显式解码,如图所示。
from mmap import mmap, ACCESS_READ
from re import compile, MULTILINE
q = compile(br'([a-z])\r\n+([a-z])', MULTILINE)
with open("regex_subst.txt", 'r', encoding='utf-8') as file, \
open("outfile.txt", "w", encoding='utf-8') as outfile, \
mmap(file.fileno(), 0, access=ACCESS_READ) as s:
outfile.write( q.sub(br" ", s).decode() )