为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

翻阅古今 2019-07-08 15:01:30
从文件中获取第n行的Bash工具有什么“规范”的方法吗?我一直在用head -n | tail -1但我一直在想,是否有一个专门从文件中提取一行(或一系列行)的Bash工具。所谓“规范”,我指的是一个程序,它的主要功能就是这样做。
查看完整描述

3 回答

?
慕莱坞森

TA贡献1810条经验 获得超4个赞

head和烟斗tail对于一个庞大的文件来说会很慢。我建议sed就像这样:

sed 'NUMq;d' file

哪里NUM要打印的行号;因此,例如,sed '10q;d' file的第10行file.

说明:

NUMq将在行号为NUM.

d将删除该行,而不是打印它;这将在最后一行上被禁止,因为q导致退出时跳过脚本的其余部分。

如果你有NUM在变量中,您需要使用双引号而不是单引号:

sed "${NUM}q;d" file


查看完整回答
反对 回复 2019-07-08
?
UYOU

TA贡献1878条经验 获得超4个赞

我有一个独特的情况,我可以基准的解决方案在这一页,所以我写这个答案,作为对建议的解决方案与每个包含的运行时间的整合。

设置

我有一个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行

  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


查看完整回答
反对 回复 2019-07-08
  • 3 回答
  • 0 关注
  • 711 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信