2016-05-17 80 views
0

我正在处理一个问题,我必须用大量文本文件中的某些行替换另一个(较小但仍然很大)的文本文件。Bash - 有效替换大文本文件中的小范围行

假设file1有10,000行,file2 3,000行。我需要执行以下类型的操作:从file2中提取901-970行,并将其插入file1的8701-8770行,替换之前的内容。在我正在处理file1的问题中,有6100万行,文件2 1800万。我需要这个操作高效地完成,因为它执行了多次 - 最终,file2的全部内容将在file1中的某处。

目前为止我所得到的最佳解决方案是将两个文件分成小文件,每个文件都有被复制和替换的块的行数(上例中为70)。事实证明,这比用头部和尾部组合提取文件的一部分要高效得多,但仍然需要触及未修改的file1部分。

我想知道是否有这样的awk/grep/sed解决方案。提取file2的一部分不是问题,但我无法弄清楚如何在不加载整个文件的情况下替换file1的一行代码块。

谢谢!

+0

你可以将文件分割成偶数行。例如:File1_1(1-900),File1_2(901_970),File1_3(971_)以及类似的File2。然后加入这些部分。 File1_1,File2_1,File1_3等。如果您的部分很大,则表示部分的数量可以管理。 – karakfa

+0

如果您的字面意思是按行数进行处理,或者如果这只是向我们展示问题范围的近似值,但您确实需要扫描特定的字符串以标记将发生替换的位置,则应明确说明。祝你好运 – shellter

+0

@karafka这也是一种可能性,但由于我需要在整个文件中做几次替换,所以我仍然有大量的节。谢谢。 – Albertini

回答

1

问题是,您必须执行随机访问类型的操作(与顺序处理不同),以“避免触及”不会更改的file1部分,并且文件的随机访问是在字符/字节级别,而不是行级别。也就是说,如果在file1中被替换的字节(与行相对)的数量与来自file2的字节的数量相同,则可以这样做(使用fseek等)。但这听起来像是没有办法保证?

因此,无论如何,您将不得不对单个文件进行一次遍历,因此该键将优化循环内的处理(通过file1行)。考虑用file1处理所有的文件2? (而不是涉及两个文件的多个操作)。

+0

实际上,file1中被替换的字节数与来自file2的字节数相匹配,所以我可以按照您的建议使用随机访问操作 - 我没有意识到这是我的问题的可能性。我用dd从file2中提取了块,并在file1中进行了替换 - 与我之前做的分割文件相比,这大约快了30%。 感谢您的帮助! – Albertini

+0

@ D.Puetzer酷!看到完整的“dd”命令会很有意思,并且所有未来在这个问题上出现的其他人都可以在类似问题上获得快速启动。 –

+0

完成,再次感谢。 – Albertini

1

遵循Jeff Y的建议,我使用dd命令在字节级有效地进行了替换。我首先使用从file2的提取块:

dd if="file2" bs="$bperelem" skip="$start_copy" count=1 of="tmp2" 2> /dev/null 

其中bperelem是块的字节,并start_copy数为所在的位置。然后,我用下面的代码替换到这个文件1:

dd if="tmp2" bs="$bperelem" skip=0 count=1 seek="$start_replace" of="file1" conv=notrunc 2> /dev/null 

对于我的特定问题的变量start_copystart_replace是一个while循环中更新。