猿问

从文件中获取第n行的Bash工具

从文件中获取第n行的Bash工具

有什么“规范”的方法吗?我一直在用head -n | tail -1但我一直在想,是否有一个专门从文件中提取一行(或一系列行)的Bash工具。

所谓“规范”,我指的是一个程序,它的主要功能就是这样做。


翻阅古今
浏览 712回答 3
3回答

慕莱坞森

head和烟斗tail对于一个庞大的文件来说会很慢。我建议sed就像这样:sed 'NUMq;d' file哪里NUM要打印的行号;因此,例如,sed '10q;d' file的第10行file.说明:NUMq将在行号为NUM.d将删除该行,而不是打印它;这将在最后一行上被禁止,因为q导致退出时跳过脚本的其余部分。如果你有NUM在变量中,您需要使用双引号而不是单引号:sed "${NUM}q;d" file

UYOU

我有一个独特的情况,我可以基准的解决方案在这一页,所以我写这个答案,作为对建议的解决方案与每个包含的运行时间的整合。设置我有一个3.261 GB的ASCII文本文件,每一行只有一个键值对。该文件总共包含3,339,550,320行,并且无法在我尝试过的任何编辑器中打开,包括我的Go-to Vim。我需要对这个文件进行子集,以便研究我所发现的一些值,这些值仅从500,000,000行左右开始。因为文件有这么多行:我只需要提取行的一个子集就可以对数据做任何有用的事情。阅读每一行,直到我关心的值,将需要很长的时间。如果解决方案读取了我关心的行,并继续读取文件的其余部分,那么它将浪费时间读取将近30亿个不相关的行,并且花费比需要长6倍的时间。我最好的解决方案是只从文件中提取一行,而不读取文件中的任何其他行,但我想不出如何在Bash中实现这一点。为了我的理智,我不会试图阅读我自己的问题所需要的全部5亿行。相反,我将尝试从3,339,550,320行中提取第50,000,000行(这意味着读取完整文件所需的时间将比需要长60倍)。我将使用time内置以对每个命令进行基准测试。基线首先让我们看看head tail解决办法:$ time head -50000000 myfile.ascii | tail -1pgm_icnt = 0real    1m15.321s第五千万行的基线是00:01:15.321,如果我直接用五亿行的话,大概是12.5分钟。切我对这件事很怀疑,但值得一试:$ time cut -f50000000 -d$'\n' myfile.ascii pgm_icnt = 0real    5m12.156s这一次花了00:05:12.156才运行,这比基线慢得多!我不确定它是读取了整个文件,还是在停止之前只读取了5000万行,但无论如何,这似乎并不是解决问题的可行方法。AWK我只使用exit因为我不打算等待完整的文件运行:$ time awk 'NR == 50000000 {print; exit}' myfile.ascii pgm_icnt = 0real    1m16.583s该代码在00:01:16.583中运行,这只比基线慢了1秒,但仍然没有对基线进行改进。按照这种速度,如果退出命令被排除在外,那么读取整个文件可能需要大约76分钟的时间!Perl我还运行了现有的Perl解决方案:$ time perl -wnl -e '$.== 50000000 && print && exit;' myfile.ascii pgm_icnt = 0real    1m13.146s该代码运行于00:01:13.146,比基线快了2秒。如果我用5亿英镑运行,大概要花12分钟。SED最重要的答案是,这是我的结果:$ time sed "50000000q;d" myfile.ascii pgm_icnt = 0real    1m12.705s该代码运行于00:01:12.705,比基线快3秒,比perl快0.4秒。如果我在完整的500,000,000行上运行它,可能需要12分钟。地图档我有bash3.1,因此不能测试mapfile解决方案。结语看起来,在大多数情况下,很难在head tail解决办法。充其量sed解决方案提高了大约3%的效率。(按公式计算的百分比)% = (runtime/baseline - 1) * 100)第50,000,000行00:01:12.705 (-00:00:02.616 = -3.47%) sed00:01:13.146 (-00:00:02.175 = -2.89%) perl00:01:15.321 (+00:00:00.000 = +0.00%) head|tail00:01:16.583 (+00:00:01.262 = +1.68%) awk00:05:12.156 (+00:03:56.835 = +314.43%) cut第500,000,000行00:12:07.050 (-00:00:26.160) sed00:12:11.460 (-00:00:21.750) perl00:12:33.210 (+00:00:00.000) head|tail00:12:45.830 (+00:00:12.620) awk00:52:01.560 (+00:40:31.650) cut第3,338,559,320行01:20:54.599 (-00:03:05.327) sed01:21:24.045 (-00:02:25.227) perl01:23:49.273 (+00:00:00.000) head|tail01:25:13.548 (+00:02:35.735) awk05:47:23.026 (+04:24:26.246) cut
随时随地看视频慕课网APP
我要回答