从文件中提取特定行的Bash命令

18

我想知道是否有更有效的方法完成这个任务。 我正在处理行数从几十万到几百万的文件。假设我知道第100,000至125,000行是包含我寻找的数据的行。我想知道是否有一种快速的方法只从文件中提取所需的行。现在我正在使用类似于grep的循环,如下所示:

 for ((i=$start_fid; i<=$end_fid; i++))
  do
    grep "^$i " fulldbdir_new >> new_dbdir${bscnt}
  done

这个工作正常运行,但需要的时间比我想象的要长。每行代码不只包含数字,基本上每行有大约10个字段,第一个字段是一个顺序整数,每个文件只出现一次。

如果必要的话,我可以使用C语言编写。

4个回答

24

sed可以完成这项工作...

sed -n '100000,125000p' input

编辑:根据glenn jackman的建议,可以进行如下调整以提高效率...

sed -n '100000,125000p; 125001q' input


4
使用 sed -n '100000,125000p; 125001q' 可以增加效率。 - glenn jackman
我认为这个答案对我有用,125000和125001之后的p和q代表什么? - mike
2
字母是告诉 sed 如何处理你正在引用的模式空间的方式。在这种情况下,'100000,125000p' 部分表示要 打印 模式空间 100000,125000(即第100000行到第125000行),而 '125001q' 部分告诉它在第125001行 退出,因为你已经得到了所需内容。 - Costa

6

I'd use awk:

awk 'NR >= 100000; NR == 125000 {exit}' file

如果数字很大,您也可以使用E表示法

awk 'NR >= 1e5; NR == 1.25e5 {exit}' file

EDIT: @glenn jackman's suggestion (cf. comment)


3
使用 NR > 125000 {exit} 可以节省时间。 - glenn jackman

2
您可以尝试组合tail和head命令来获取正确的行。
head -n 125000 file_name | tail -n 25001 | grep "^$i "

不要忘记还有Perl。
perl -ne 'print if $. >= 100000 && $. <= 125000' file_name | grep "^$i "

或者使用更快的 Perl:
perl -ne 'print if $. >= 100000; exit() if $. >= 100000 && $. <= 125000' | grep "^$i "

另外,你可能希望使用GNU parallel而不是for循环。


1
到目前为止,答案读取了前100000行并将其丢弃。由于磁盘I/O通常是限制因素,因此最好有一种不必读取不需要的行的解决方案。
如果前100000行总长度(大约)相同,则可以计算出距离文件开头约100000行的位置,然后读取接下来的25000行。可能在前后多读一些内容以确保您获得所有的25000行。
但是,您将无法确切知道自己在哪一行,这可能很重要,也可能不重要。
假设前100000行的平均行长度为130,则会得到类似以下的结果:
 dd if=the_file skip=130 bs=100000 | head -n 25000

你需要丢弃第一行,因为它很可能只是半行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接