在大型文本文件(19 GB)上使用“head”或“tail”

在大型文本文件(19 GB)上使用“head”或“tail”

我在查看非常大的文本文件块时遇到了问题。这个文件大约有 19 GB,显然太大了,无法通过任何传统方式查看。

head 1我尝试过tail 1将两个命令以各种方式连接在一起(以得到中间的部分),但没有成功。我的 Linux 机器运行的是 Ubuntu 9.10,无法处理此文件head -n 1tail -n 1

我该如何处理这个文件?我的最终目标是专注于第 45000000 行和第 45000100 行。

答案1

您应该使用sed

sed -n -e 45000000,45000100p -e 45000101q bigfile > savedlines

这告诉sed打印第 45000000 行至第 45000100 行(含),并在第 45000101 行退出。

答案2

创建一个包含单个字段的单个表的 MySQL 数据库。然后将文件导入数据库。这样可以非常轻松地查找某一行。

我认为没有其他方法可以更快(如果head已经tail失败)。最后,想要查找行的应用程序n必须搜索整个文件,直到找到n换行符。如果没有某种查找(行索引到文件中的字节偏移量),就无法实现更好的性能。

考虑到创建 MySQL 数据库和将数据导入其中非常容易,我觉得这是一种可行的方法。

具体操作如下:

DROP DATABASE IF EXISTS helperDb;
CREATE DATABASE `helperDb`;
CREATE TABLE `helperDb`.`helperTable`( `lineIndex` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `lineContent` MEDIUMTEXT , PRIMARY KEY (`lineIndex`) );
LOAD DATA INFILE '/tmp/my_large_file' INTO TABLE helperDb.helperTable (lineContent);
SELECT lineContent FROM helperTable WHERE ( lineIndex > 45000000 AND lineIndex < 45000100 );

/tmp/my_large_file就是您想要读取的文件。

导入每行具有制表符分隔值的文件的正确语法是:

LOAD DATA INFILE '/tmp/my_large_file' INTO TABLE helperDb.helperTable FIELDS TERMINATED BY '\n' (lineContent);

这样做的另一个主要优点是,如果您稍后决定提取另一组行,则不必再次等待数小时进行处理(当然,除非您删除数据库)。

答案3

两个处理大文件的好用的老工具是joinsplit。您可以使用 split--lines=<number>选项将文件剪切为多个特定大小的文件。

例如split --lines=45000000 huge_file.txt。结果部分将位于 xa、xb 等中。然后,您可以将head部分討厭它将包含您想要的行。您还可以将文件“合并”回单个大文件。

答案4

你有正确的工具,但使用方式不正确。如前所述已回答在 U&L 上,tail -n +X file | head -n Y(注意+)比从 X 开始的 Y 线快 10-15% sed。并且方便的是,您不必exit像那样明确地执行该过程sed

tail 将读取并丢弃前 X-1 行(这是无法避免的),然后读取并打印以下行。head 将读取并打印请求的行数,然后退出。当 head 退出时,tail 会收到 SIGPIPE 信号并终止,因此它不会从输入文件中读取超过缓冲区大小(通常为几千字节)的行。

相关内容