从文本文件中取出片段的最佳方法是什么?

从文本文件中取出片段的最佳方法是什么?

从一个巨大的文本文件中提取第 20 -45 行的好方法是什么?当然是非交互的!

答案1

更简单:

sed -n '20,45p;45q' < textfile

-n 标志禁用默认输出。 “20,45”寻址第 20 行到第 45 行(含)。 “p”命令打印当前行。打印该行后 q 退出。

答案2

你可以尝试:

cat textfile | head -n 45 | tail -n 26

或者

cat textfile | awk "20 <= NR && NR <= 45" 

更新:

正如 Mahomedalid 指出的那样,cat这不是必需的,而且有点多余,但它确实是一个干净、可读的命令。

如果cat确实困扰您,更好的解决方案是:

<textfile awk "20 <= NR && NR <= 45"

答案3

这不是答案,但无法将其作为评论发布。

另一种(非常快)的方法是由麦克塞夫 这里:

{ head -n 19 >/dev/null; head -n 26; } <infile

使用相同的测试文件这里和相同的过程,这里有一些基准(提取行1000020-1000045):

麦克塞夫:

{ head -n 1000019 >/dev/null; head -n 26; } <iplist

real    0m0.059s

斯特凡:

head iplist -n 1000045 | tail -n 26

real    0m0.054s

这些是迄今为止最快的解决方案,并且差异可以忽略不计(对于单次通过)(我尝试了不同的范围:几行,数百万行等)。

然而,对于需要寻找管道的应用程序来说,在没有管道的情况下执行此操作可能会提供显着的优势多个范围类似方式的线条,例如:

for  pass in 0 1 2 3 4 5 6 7 8 9
do   printf "pass#$pass:\t"
     head -n99 >&3; head -n1
done <<1000LINES 3>/dev/null
$(seq 1000)
1000LINES

...打印...

pass#0: 100
pass#1: 200
pass#2: 300
pass#3: 400
pass#4: 500
pass#5: 600
pass#6: 700
pass#7: 800
pass#8: 900
pass#9: 1000

...并且只读取一次文件。


其他sed//解决方案读取整个文件,并且由于这是关于大文件,awk因此perl它们效率不高。我在指定范围内的最后一行之后 exit添加了一些替代方案:q

斯特凡:

awk "1000020 <= NR && NR <= 1000045" iplist

real    0m2.448s

awk "NR >= 1000020;NR==1000045{exit}" iplist

real    0m0.243s

德卡格达尔( sed):

sed -n 1000020,1000045p iplist

real    0m0.947s

sed '1,1000019d;1000045q' iplist

real    0m0.143s

史蒂文·D:

perl -ne 'print if 1000020..1000045' iplist

real    0m2.041s

perl -ne 'print if $. >= 1000020; exit if $. >= 1000045;' iplist

real    0m0.369s

答案4

由于 sed 和 awk 已经被采用,这里是一个 perl 解决方案:

perl -nle "print if ($. > 19 && $. < 46)" < textfile

或者,正如评论中指出的:

perl -ne 'print if 20..45' textfile

相关内容