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


Answers:


12

您可以尝试:

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

要么

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

更新:

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

如果cat打扰您,那么更好的解决办法是:

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

2
awk NR==20,NR==45 textfile也可以使用,并且易于阅读。
短暂

我更喜欢使用stdin,它与nix的其余部分具有一定的全局一致性
Stefan 2010年

1
从命令行参数读取也与其他UNIX实用程序一致,我的主要观点是演示awk的,范围运算符。
短暂

大声笑,我的意思是@adam。但是,是的,我喜欢您的建议
Stefan

我认为@ephemient的答案是最好的答案。否则,这些命令将非常隐秘。
莱奥波德·赫兹(LéoLéopoldHertz)2015年

13

更简单:

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

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


1
+1不错,我喜欢,但是它的20至45行:)
Stefan

1
好吧好吧,我将其编辑为20,45 :-)
dkagedal 2010年

从27169334行文件中提取单行26995107时,删除该q命令(所有从开头的命令;)对我来说都提高了性能。
罗斯兰

6

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

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

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

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

mikeserv

{ 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解决方案读取整个文件,因为这是对大型文件,他们不是非常有效。我在指定范围的最后一行之后添加了一些替代方法exitquit:

斯蒂芬

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

real    0m2.448s

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

real    0m0.243s

dkagedalsed):

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

+1我认为这是最好的答案!花费很多时间awk NR==1000020,NR==1000045 textfile在您的系统中会很高兴。
莱奥波尔德·赫兹(LéoLéopoldHertz)2015年

3
ruby -ne 'print if 20 .. 45' file

1
一个红宝石专家,你得到我的投票先生
Stefan

1
当我们这样做时,为什么不python -c 'import fileinput, sys; [sys.stdout.write(line) for nr, line in enumerate(fileinput.input()) if 19 <= nr <= 44]'呢?:-P这是受Perl启发,受awk / sed启发的Ruby可以轻松实现的。
短暂

2

由于已经使用了sed和awk,因此这是一个perl解决方案:

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

或者,如评论中指出的那样:

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

2
所有这些多余的字符是什么?无需剥离和重新添加换行符,触发器假定与行号进行比较,并且菱形运算符通过参数运行(如果提供)。 perl -ne'print if 20..45' textfile
短暂

1
真好 -nle我想是一种反思,至于其余的话,除了无知之外,我没有任何借口。
史蒂文D
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.