如何在Unix中提取第三大的文件大小

14 浏览
0 Comments

如何在Unix中提取第三大的文件大小

有没有一种“规范”的方法来做这件事?我一直在使用head -n | tail -1这种方法,它能达到目的,但我一直在想是否有一种Bash工具专门用来从文件中提取一行(或一系列行)。\n所谓“规范”,指的是一个主要功能是做这件事的程序。

0
0 Comments

在Unix系统上提取第三大文件大小的问题出现的原因是,用户有一个3.261GB的ASCII文本数据文件,每行一个键值对。该文件总共包含3,339,550,320行,并且无法在任何编辑器中打开,包括常用的Vim。用户需要对这个文件进行子集提取,以便研究一些发现,这些值只出现在大约第5,000,000,000行左右。由于文件包含如此多的行:

- 用户需要提取只有一部分行来对数据进行有意义的操作。

- 遍历到我关心的值之前的每一行将需要很长时间。

- 如果解决方案读取超过我关心的行并继续读取文件的其余部分,它将浪费时间读取近30亿个无关的行,所需时间将是必要时间的6倍。

用户最理想的解决方案是只从文件中提取一行,而不读取文件中的其他行,但用户无法想到如何在Bash中实现这一点。为了保持自己的理智,用户不会尝试读取自己问题所需的完整的5,000,000,000行。相反,用户将尝试提取3,339,550,320行中的第50,000,000行(这意味着读取整个文件将需要多出60倍的时间)。

用户使用time内置命令对每个命令进行基准测试。

首先看看head tail解决方案的基准测试:

$ time head -50000000 myfile.ascii | tail -1
pgm_icnt = 0
real    1m15.321s

50,000,000行的基准测试时间为00:01:15.321,如果直接选择500,000,000行,可能需要大约12.5分钟。

接下来尝试使用cut命令:

$ time cut -f50000000 -d$'\n' myfile.ascii
pgm_icnt = 0
real    5m12.156s

这个命令运行时间为00:05:12.156,比基准测试慢得多!不确定它是否读取了整个文件或只是在第50,000,000行之前停止,但不管怎样,这似乎不是问题的可行解决方案。

接下来尝试使用AWK命令:

$ time awk 'NR == 50000000 {print; exit}' myfile.ascii
pgm_icnt = 0
real    1m16.583s

这个命令运行时间为00:01:16.583,只比基准测试慢了大约1秒,但仍然没有改进。按这个速度,如果不使用exit命令,它可能需要大约76分钟才能读取整个文件!

接下来尝试使用Perl命令:

$ time perl -wnl -e '$.== 50000000 && print && exit;' myfile.ascii
pgm_icnt = 0
real    1m13.146s

这个命令运行时间为00:01:13.146,比基准测试快了大约2秒。如果在完整的500,000,000行上运行它,可能需要大约12分钟。

最后尝试使用sed命令,这是排名第一的答案:

$ time sed "50000000q;d" myfile.ascii
pgm_icnt = 0
real    1m12.705s

这个命令运行时间为00:01:12.705,比基准测试快了3秒,比Perl快了约0.4秒。如果在完整的500,000,000行上运行它,可能需要大约12分钟。

总结来看,大多数情况下,很难改进head tail解决方案。最好的情况是,sed解决方案提供了约3%的效率提升。

50,000,000行的结果:

1. 00:01:12.705 (-00:00:02.616 = -3.47%) sed

2. 00:01:13.146 (-00:00:02.175 = -2.89%) perl

3. 00:01:15.321 (+00:00:00.000 = +0.00%) head|tail

4. 00:01:16.583 (+00:00:01.262 = +1.68%) awk

5. 00:05:12.156 (+00:03:56.835 = +314.43%) cut

500,000,000行的结果:

1. 00:12:07.050 (-00:00:26.160) sed

2. 00:12:11.460 (-00:00:21.750) perl

3. 00:12:33.210 (+00:00:00.000) head|tail

4. 00:12:45.830 (+00:00:12.620) awk

5. 00:52:01.560 (+00:40:31.650) cut

3,338,559,320行的结果:

1. 01:20:54.599 (-00:03:05.327) sed

2. 01:21:24.045 (-00:02:25.227) perl

3. 01:23:49.273 (+00:00:00.000) head|tail

4. 01:25:13.548 (+00:02:35.735) awk

5. 05:47:23.026 (+04:24:26.246) cut

用户感到好奇,将整个文件通过cat命令重定向到/dev/null需要多长时间。(如果这只是一个硬盘基准测试会怎样呢?)

用户对于你拥有一个3GB以上的文本文件字典感到非常好奇。无论理由是什么,这确实非常注重文本性质。

对于单个文件,运行head + tail两个进程的开销是可以忽略不计的,但当您对多个文件执行此操作时,就会开始显示出来。

0
0 Comments

在Unix中提取第三大文件大小的方法是通过使用以下命令:

ls -lS | awk 'NR==3 {print $5}'

这个问题的出现是因为用户想要找到文件系统中第三大的文件大小。解决方法是使用ls命令以及awk命令来实现。

ls命令用于列出文件和目录,-l选项表示使用长格式显示,-S选项表示按文件大小排序。接下来,使用管道将ls命令的输出传递给awk命令。

awk是一种用于处理文本文件的编程语言。在这个命令中,NR==3表示只处理第三行,{print $5}表示打印第五列,即文件大小。

通过这个命令,用户可以得到文件系统中第三大文件的大小。

这个方法的好处是简单、直接,不需要编写复杂的脚本。它只需要几个简单的命令就可以实现目标。

然而,这个方法也有一些限制。首先,它只能找到文件系统中第三大的文件,无法找到其他位置的文件。其次,它依赖于ls命令的输出格式,如果ls命令的输出格式发生变化,那么这个方法可能就无法正常工作。

通过使用ls和awk命令结合,可以方便地提取文件系统中第三大文件的大小。这个方法简单直接,适用于一般的文件大小查找任务。

0
0 Comments

问题的原因:

有一个要求从Unix中提取第三个最大的文件大小的需求。然而,已经提供的解决方法使用了head和tail命令,这对于大文件来说会很慢。因此,需要找到一种更高效的解决方法。

解决方法:

一种更高效的解决方法是使用sed命令。可以使用以下命令提取第三个最大的文件大小:

sed '3q;d' file

这个命令会打印出文件的第三行内容。

解释:

3q会在行号为3时立即退出。

d会删除该行而不是打印出来;在最后一行,因为q导致脚本的剩余部分被跳过,所以不会被删除。

如果行号是一个变量,可以使用双引号而不是单引号:

sed "${NUM}q;d" file

另外,某些情况下使用tail -n+NUM file | head -n1可能同样快或者更快。至少在我使用NUM为250000、文件有50万行的情况下,速度要快得多。你可以通过将head -n1更改为head -nNUM2来选择在此点之后的行数。

如果要提取从第n行到第m行的范围,可以使用以下命令:

sed -n 'n,m{p;mq;}' file

这是一个很好的解决方法,但是如果要将sed命令的输出分配给一个变量,使用命令替换可能不起作用,如果返回的行包含双星号的话。例如,如果sed "4q;d" file4返回** banana,那么foo=$(sed "4q;d" file4)将把file1 file2 file3 file4 banana分配给变量foo。解决这个问题的方法是使用引号将命令替换起来,即foo="$(sed "4q;d" file4)"

最后,有人将这个解决方法制作成了一个脚本,可以从命令行接收参数,如果没有指定文件,则从标准输入中读取。脚本的使用方法是:nth line [file]。具体的脚本可以在这里找到。

对于文件太短而没有这样一行的情况,输出将为空。

通过使用sed命令,可以更高效地提取第三个最大的文件大小,而不会导致性能下降。

0