如何在 Unix 中替换 40GB 文件中的两个字符?
How can I replace two characters in a 40GB file in Unix?
我有两个巨大的 json 文件(每个 20GB),我需要加入它们。这些文件具有以下内容:
file_1.json = [{"key": "value"}, {...}]
file_2.json = [{"key": "value"}, {...}]
然而,主要问题是我需要所有的字典都在同一个列表中。我尝试在 python 中执行此操作,但不幸的是,我没有内存来执行此操作。
所以,我想也许我可以用 unix 命令来解决这个问题,方法是在第一个文件中,将 ]
替换为 ,
(注意后面有一个 space逗号)并从第二个文件中删除 [
。然后,我将使用 cat
unix 命令加入这两个文件。
有没有办法让我在 unix 中只编辑最后 10 个字符?
我尝试使用 echo
和 tr
,但我的语法可能有问题。
您可以非常轻松地就地附加到文件,即在末尾添加字符,而无需重写已经存在的数据。使用正确的工具(truncate
如果您的系统有它),您可以就地截断文件,即删除末尾的字符而不重写保留的数据。使用正确的工具(dd
,如果您喜欢冒险),您可以用相同长度的字符串替换文件的一部分,而无需重写未更改的部分。另一方面,您不能在不重写文件的情况下从文件的开头或中间删除字符(除了一些与此处无关的例外)。
但是无论如何,就地重写这两个文件对您没有太大帮助。您至少需要重写第二个文件的内容才能将其附加到第一个文件。
如果您不需要保留拆分后的文件,您可以在处理中间标点符号后将第二个文件追加到第一个文件中。从第一个文件中删除最后一个 ]
字符,以及所有后续空格和换行符。假设第一个文件以 ]
和一个换行符结尾,并且您有 GNU 核心实用程序(例如 non-embedded Linux):
truncate -s -2 file_1.json
现在您可以在第一个文件中添加逗号和可选的换行符,并附加第二个文件中的数据,但不包含第一个字符。
echo , >>file_1.json
tail -c +2 file_2.json >>file_1.json
如果您想保持原始文件不被修改,您可以复制第一个文件并将其截断。或者你可以直接制作第一个文件的截断副本(仍然假设 GNU coreutils):
head -c -2 file_1.json >concatenated.json
echo , >>concatenated.json
tail -c +2 file_2.json >>concatenated.json
如果您更习惯 Python,您可以在 Python 中完成所有这些操作。只是不要一次读取整个文件,即不要以一次读取所有行的方式调用 read()
或使用 readline()
。相反,一次读取和处理一行(如果行很短)或一个数据块。未经测试的代码:
with open('concatenated.json', 'wb') as out:
with open('file_1.json', 'rb') as inp:
buf = bytes(1024)
size = inp.seek(-len(buf), io.SEEK_END)
n = inp.readinto(buf)
m = re.search(rb']\s*\Z', buf)
stop_at = m.start()
inp.seek(0, io.SEEK_SET)
n = inp.readinto(buf)
total = n
while n > 0:
out.write(buf)
n = inp.readinto(buf)
total += n
if total > stop_at:
out.write(buf[:len(buf)-(total-stop_at)])
n = 0
out.write(b',')
with open('file_2.json', 'rb') as inp:
buf = bytes(1024)
n = inp.readinto(buf)
assert buf[0] == b'['
buf[0:1] = b'\n'
while n > 0:
out.write(buf)
n = inp.readinto(buf)
我有两个巨大的 json 文件(每个 20GB),我需要加入它们。这些文件具有以下内容:
file_1.json = [{"key": "value"}, {...}]
file_2.json = [{"key": "value"}, {...}]
然而,主要问题是我需要所有的字典都在同一个列表中。我尝试在 python 中执行此操作,但不幸的是,我没有内存来执行此操作。
所以,我想也许我可以用 unix 命令来解决这个问题,方法是在第一个文件中,将 ]
替换为 ,
(注意后面有一个 space逗号)并从第二个文件中删除 [
。然后,我将使用 cat
unix 命令加入这两个文件。
有没有办法让我在 unix 中只编辑最后 10 个字符?
我尝试使用 echo
和 tr
,但我的语法可能有问题。
您可以非常轻松地就地附加到文件,即在末尾添加字符,而无需重写已经存在的数据。使用正确的工具(truncate
如果您的系统有它),您可以就地截断文件,即删除末尾的字符而不重写保留的数据。使用正确的工具(dd
,如果您喜欢冒险),您可以用相同长度的字符串替换文件的一部分,而无需重写未更改的部分。另一方面,您不能在不重写文件的情况下从文件的开头或中间删除字符(除了一些与此处无关的例外)。
但是无论如何,就地重写这两个文件对您没有太大帮助。您至少需要重写第二个文件的内容才能将其附加到第一个文件。
如果您不需要保留拆分后的文件,您可以在处理中间标点符号后将第二个文件追加到第一个文件中。从第一个文件中删除最后一个 ]
字符,以及所有后续空格和换行符。假设第一个文件以 ]
和一个换行符结尾,并且您有 GNU 核心实用程序(例如 non-embedded Linux):
truncate -s -2 file_1.json
现在您可以在第一个文件中添加逗号和可选的换行符,并附加第二个文件中的数据,但不包含第一个字符。
echo , >>file_1.json
tail -c +2 file_2.json >>file_1.json
如果您想保持原始文件不被修改,您可以复制第一个文件并将其截断。或者你可以直接制作第一个文件的截断副本(仍然假设 GNU coreutils):
head -c -2 file_1.json >concatenated.json
echo , >>concatenated.json
tail -c +2 file_2.json >>concatenated.json
如果您更习惯 Python,您可以在 Python 中完成所有这些操作。只是不要一次读取整个文件,即不要以一次读取所有行的方式调用 read()
或使用 readline()
。相反,一次读取和处理一行(如果行很短)或一个数据块。未经测试的代码:
with open('concatenated.json', 'wb') as out:
with open('file_1.json', 'rb') as inp:
buf = bytes(1024)
size = inp.seek(-len(buf), io.SEEK_END)
n = inp.readinto(buf)
m = re.search(rb']\s*\Z', buf)
stop_at = m.start()
inp.seek(0, io.SEEK_SET)
n = inp.readinto(buf)
total = n
while n > 0:
out.write(buf)
n = inp.readinto(buf)
total += n
if total > stop_at:
out.write(buf[:len(buf)-(total-stop_at)])
n = 0
out.write(b',')
with open('file_2.json', 'rb') as inp:
buf = bytes(1024)
n = inp.readinto(buf)
assert buf[0] == b'['
buf[0:1] = b'\n'
while n > 0:
out.write(buf)
n = inp.readinto(buf)