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

Chr*_*ver 14 command-line text-processing

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

dka*_*dal 13

更简单:

sed -n '20,45p;45q' < textfile
Run Code Online (Sandbox Code Playgroud)

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


Ste*_*fan 12

你可以试试:

cat textfile | head -n 45 | tail -n 26
Run Code Online (Sandbox Code Playgroud)

或者

cat textfile | awk "20 <= NR && NR <= 45" 
Run Code Online (Sandbox Code Playgroud)

更新:

正如 Mahomedalid 指出的那样,cat这不是必需的,而且有点多余,但它确实使命令清晰易读。

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

<textfile awk "20 <= NR && NR <= 45"
Run Code Online (Sandbox Code Playgroud)

  • `awk NR==20,NR==45 textfile` 也可以工作,并且很容易阅读。 (4认同)
  • 从命令行参数读取也与其他 UNIX 实用程序一致,我的主要观点是演示 awk 的 `,` 范围运算符。 (2认同)

don*_*sti 7

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

mikeserv 在这里建议了另一种(非常快的)方法:

{ head -n 19 >/dev/null; head -n 26; } <infile
Run Code Online (Sandbox Code Playgroud)

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

迈克服务

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

real    0m0.059s
Run Code Online (Sandbox Code Playgroud)

斯蒂芬

head iplist -n 1000045 | tail -n 26

real    0m0.054s
Run Code Online (Sandbox Code Playgroud)

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

但是,在没有管道的情况下执行此操作可能会为需要以类似方式搜索多个范围的行的应用程序提供显着优势,例如:

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
Run Code Online (Sandbox Code Playgroud)

...打印...

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
Run Code Online (Sandbox Code Playgroud)

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


其他sed/ awk/perl解决方案读取整个文件,因为这是对大型文件,他们不是非常有效。我在一些替代扔的exitqUIT在指定范围内的最后一行后:

斯蒂芬

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

real    0m2.448s
Run Code Online (Sandbox Code Playgroud)

对比

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

real    0m0.243s
Run Code Online (Sandbox Code Playgroud)

dkagedal ( sed):

sed -n 1000020,1000045p iplist

real    0m0.947s
Run Code Online (Sandbox Code Playgroud)

对比

sed '1,1000019d;1000045q' iplist

real    0m0.143s
Run Code Online (Sandbox Code Playgroud)

史蒂文D

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

real    0m2.041s
Run Code Online (Sandbox Code Playgroud)

对比

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

real    0m0.369s
Run Code Online (Sandbox Code Playgroud)