从文件中提取特定行

时间:2014-01-05 18:13:47

标签: bash shell

我有一个文件,我想从该文件中提取特定行,如第2,10,15,21 ......等等。从文件中提取大约20万行。我怎样才能在bash中有效地做到这一点

6 个答案:

答案 0 :(得分:1)

也许正在寻找: sed -n -e 1p -e 4p afile

答案 1 :(得分:1)

将所需行的亚麻布放在名为“想要”的文件中,如下所示:

2
10
15
21

然后运行此脚本:

#!/bin/bash
while read w
do
   sed -n ${w}p yourfile
done < wanted

完全替代方法

或者你可以让“awk”为你做这一切,比如这可能要快几英里,因为你不必创建200,000个sed进程:

awk 'FNR==NR{a[$1]=1;next}{if(FNR in a){print;}}' wanted yourfile

FNR == NR部分检测到awk何时正在读取名为“想要”的文件,如果是,则将数组“a”的元素“$ 1”设置为“1”,因此我们知道该行号是需要的。第二组花括号中的东西在处理较大的文件时是活动的,如果它的亚麻布在我们在读取“想要的”文件时创建的数组“a”中,它会打印当前行。

答案 2 :(得分:1)

$ gawk 'ARGIND==1 { L[$0]++ }; ARGIND==2 && FNR in L' lines file > file.lines

通缉行号必须存储在换行符分隔的lines中,并且可以安全地按随机顺序排列。它与@Mark Setchell的第二种方法几乎完全相同,但使用更清晰的方法来确定哪个文件是最新的。虽然此ARGIND是GNU扩展,但gawk。如果您仅限于原始AWK或mawk,则可以将其写为:

$ awk 'FILENAME==ARGV[1] { L[$0]++ }; FILENAME==ARGV[2] && FNR in L' lines file > file.lines

效率测试:

$ awk 'BEGIN { for (i=1; i<=1000000; i++) print i }' > file
$ shuf -i 1-1000000 -n 200000 > lines
$ time gawk 'ARGIND==1 { L[$0]++ }; ARGIND==2 && FNR in L' lines file > file.lines

real    0m1.734s
user    0m1.460s
sys     0m0.052s

UPD:

正如@Costi Ciudatu指出的那样,当所有想要的行都在文件的头部时,这个案子还有空间。

#!/usr/bin/gawk -f

ARGIND==1 { L[$0]++ }
ENDFILE { L_COUNT = FNR }

ARGIND==2 && FNR in L { L_PRINTED++; print }
ARGIND==2 && L_PRINTED == L_COUNT { exit 0 }

当打印最后一行时,Sript会中断,所以现在需要几毫秒来从一百万行文件的前1%中过滤掉2000条随机行。

$ time ./getlines.awk lines file > file.lines

real    0m0.016s
user    0m0.012s
sys     0m0.000s

虽然阅读整个文件仍然需要大约一秒钟。

$ time gawk 'ARGIND==1 { L[$0]++ }; ARGIND==2 && FNR in L' lines file > file.lines

real    0m0.780s
user    0m0.756s
sys     0m0.016s

答案 3 :(得分:0)

如果您的系统支持sed -f -(即sed在标准输入上读取其脚本;它适用于Linux,但不适用于其他某些平台)您可以将行号文件转换为sed脚本,自然使用sed

sed 's/$/p/' lines | sed -n -f - inputfile >output

答案 4 :(得分:0)

如果您感兴趣的行靠近文件的开头,则可以使用headtail来有效地提取特定行。

对于您的示例行号(假设列表在接近200,000之前不会继续),读取这些行的虚拟但仍然有效的方法如下:

for n in 2 10 15 21; do
    head -n $n /your/large/file | tail -1
done

答案 5 :(得分:-1)

sed示例

sed -n '2p' file

awk示例

awk 'NR==2' file

这将打印第二行文件

在循环中使用相同的逻辑尝试。

说一个for循环

for VARIABLE in 2 10 15 21 
  do
    awk "NR==$VARIABLE" file

 done

以这种方式提供您的行号。