我正在解决一个问题,我必须用另一个(较小但仍然很大)的文本文件中的数据替换大文本文件中的某一系列行。
假设file1有10,000行,file2有3,000行。我需要执行类型的操作:从file2中提取行901-970并将其插入到file1的行8701-8770中,替换之前的行。在我正在研究的问题上,file1有6100万行,而file2有1800万行。我需要这个操作有效地完成,因为它执行了几次 - 最后file2的整个内容将在file1中的某个地方。
到目前为止,我得到的最佳解决方案是将两个文件分成小文件,每个文件都有复制和替换的块的行数(上例中为70)。事实证明,这比头尾组合提取文件的部分效率要高得多,但仍需要触摸未经修改的文件1的部分。
我想知道是否有一个awk / grep / sed解决方案。提取文件2的一部分不是问题,但我无法弄清楚如何在不加载整个文件的情况下替换file1的一行行。
谢谢!
答案 0 :(得分:1)
问题是你必须做一个随机访问类型的操作(与顺序处理不同)到"避免触摸" file1的部分不会改变,文件的随机访问是字符/字节级别,而不是行级别。也就是说,如果在file1中替换的 bytes (而不是行)的数量与来自file2的 bytes 的数量相同,则可以这样做(使用fseek之类的)。但听起来似乎无法保证?
所以无论如何你都必须对file1进行单次传递,因此密钥将优化循环内的处理(通过file1行)。考虑通过file1一次传递处理file2的所有部分? (而不是涉及两个文件的多个操作。)
答案 1 :(得分:1)
根据Jeff Y的建议,我使用dd命令在字节级别有效地进行替换。我首先使用:
从file2中提取一个块dd if="file2" bs="$bperelem" skip="$start_copy" count=1 of="tmp2" 2> /dev/null
其中bperelem
是块的字节数,start_copy
是它所在的位置。然后我使用以下内容将其替换为file1:
dd if="tmp2" bs="$bperelem" skip=0 count=1 seek="$start_replace" of="file1" conv=notrunc 2> /dev/null
对于我的具体问题,变量start_copy
和start_replace
会在while循环中更新。