有没有一种“规范”的方法?我一直在使用head-n|tail-1来完成这个任务,但我一直在想是否有一个Bash工具专门从文件中提取一行(或一系列行)。
我所说的“规范”是指一个主要功能就是这样做的程序。
有没有一种“规范”的方法?我一直在使用head-n|tail-1来完成这个任务,但我一直在想是否有一个Bash工具专门从文件中提取一行(或一系列行)。
我所说的“规范”是指一个主要功能就是这样做的程序。
当前回答
作为CaffeineConnisseur非常有用的基准测试答案的后续。。。我很好奇“mapfile”方法与其他方法相比的速度有多快(因为没有测试),所以我自己尝试了一个快速而肮脏的速度比较,因为我手边有bash 4。在我做这项测试时,我在顶部答案的一条评论中提到了“tail|head”方法(而不是head|tail),因为人们都在称赞它。我没有使用的测试文件的大小;我能在短时间内找到的最好的文件是一个14M的谱系文件(用空格分隔的长行,略低于12000行)。
短版本:mapfile看起来比cut方法快,但比其他任何方法都慢,所以我称它为无用的。tail|head,OTOH,看起来可能是最快的,尽管与sed相比,这种大小的文件差异并不大。
$ time head -11000 [filename] | tail -1
[output redacted]
real 0m0.117s
$ time cut -f11000 -d$'\n' [filename]
[output redacted]
real 0m1.081s
$ time awk 'NR == 11000 {print; exit}' [filename]
[output redacted]
real 0m0.058s
$ time perl -wnl -e '$.== 11000 && print && exit;' [filename]
[output redacted]
real 0m0.085s
$ time sed "11000q;d" [filename]
[output redacted]
real 0m0.031s
$ time (mapfile -s 11000 -n 1 ary < [filename]; echo ${ary[0]})
[output redacted]
real 0m0.309s
$ time tail -n+11000 [filename] | head -n1
[output redacted]
real 0m0.028s
希望这有帮助!
其他回答
要使用sed和变量作为行号打印第n行,请执行以下操作:
a=4
sed -e $a'q:d' file
这里的“-e”标志用于将脚本添加到要执行的命令中。
哇,所有的可能性!
试试看:
sed -n "${lineNum}p" $file
或者根据您的Awk版本选择其中之一:
awk -vlineNum=$lineNum 'NR == lineNum {print $0}' $file
awk -v lineNum=4 '{if (NR == lineNum) {print $0}}' $file
awk '{if (NR == lineNum) {print $0}}' lineNum=$lineNum $file
(您可能需要尝试nawk或gawk命令)。
是否有一种工具只打印特定的行?不是标准工具之一。然而,sed可能是最接近和最简单的用法。
sed -n '2p' < file.txt
将打印第二行
sed -n '2011p' < file.txt
2011线
sed -n '10,33p' < file.txt
第10行到第33行
sed -n '1p;3p' < file.txt
第1和第3行
等等
对于使用sed添加行,您可以选中此项:
sed:在某个位置插入一行
如果有多行由\n分隔(通常为新行)。您也可以使用“cut”:
echo "$data" | cut -f2 -d$'\n'
您将从文件中获得第二行-f3给你第三行。
有了awk,速度相当快:
awk 'NR == num_line' file
如果为true,则执行awk的默认行为:{print$0}。
替代版本
如果您的文件恰好很大,最好在读取所需的行后退出。这样可以节省CPU时间请参见答案末尾的时间比较。
awk 'NR == num_line {print; exit}' file
如果要从bash变量中给出行号,可以使用:
awk 'NR == n' n=$num file
awk -v n=$num 'NR == n' file # equivalent
查看使用exit节省了多少时间,特别是如果该行恰好位于文件的第一部分:
# Let's create a 10M lines file
for ((i=0; i<100000; i++)); do echo "bla bla"; done > 100Klines
for ((i=0; i<100; i++)); do cat 100Klines; done > 10Mlines
$ time awk 'NR == 1234567 {print}' 10Mlines
bla bla
real 0m1.303s
user 0m1.246s
sys 0m0.042s
$ time awk 'NR == 1234567 {print; exit}' 10Mlines
bla bla
real 0m0.198s
user 0m0.178s
sys 0m0.013s
因此,两者的差异是0.198秒对1.303秒,大约快了6倍。