有没有一种“规范”的方法?我一直在使用head-n|tail-1来完成这个任务,但我一直在想是否有一个Bash工具专门从文件中提取一行(或一系列行)。
我所说的“规范”是指一个主要功能就是这样做的程序。
有没有一种“规范”的方法?我一直在使用head-n|tail-1来完成这个任务,但我一直在想是否有一个Bash工具专门从文件中提取一行(或一系列行)。
我所说的“规范”是指一个主要功能就是这样做的程序。
当前回答
您也可以使用Perl实现这一点:
perl -wnl -e '$.== NUM && print && exit;' some.file
其他回答
保存两次按键,不使用括号打印第N行:
sed -n Np <fileName>
^ ^
\ \___ 'p' for printing
\______ '-n' for not printing by default
例如,要打印第100行:
sed -n 100p foo.txt
要使用sed和变量作为行号打印第n行,请执行以下操作:
a=4
sed -e $a'q:d' file
这里的“-e”标志用于将脚本添加到要执行的命令中。
作为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
希望这有帮助!
UPDATE 1:在awk中找到了更快的方法
仅需5.353秒即可获得133.6 mn以上的行:
行号='133668997';(时间(pvE0<~/master_primelist_18a.txt|LC_ALL=C mawk2-F'^$'-v\_=“${rownum}”--'_{exit}!--_'))
in0: 5.45GiB 0:00:05 [1.02GiB/s] [1.02GiB/s] [======> ] 71%
( pvE 0.1 in0 < ~/master_primelist_18a.txt |
LC_ALL=C mawk2 -F'^$' -v -- ; ) 5.01s user
1.21s系统116%cpu 5.353总计
77.37219=195591955519519519559551=0x296B0FA7D668C4A64F7F=
===============================================
我想质疑perl比awk更快的观点:
因此,虽然我的测试文件的行数没有那么多,但它的大小也是原来的两倍,为7.58GB-
我甚至给了perl一些内置的优势——比如行号中的硬编码,并且还排在第二位,从而从OS缓存机制中获得了任何潜在的加速(如果有的话)
f="$( grealpath -ePq ~/master_primelist_18a.txt )"
rownum='133668997'
fg;fg; pv < "${f}" | gwc -lcm
echo; sleep 2;
echo;
( time ( pv -i 0.1 -cN in0 < "${f}" |
LC_ALL=C mawk2 '_{exit}_=NR==+__' FS='^$' __="${rownum}"
) ) | mawk 'BEGIN { print } END { print _ } NR'
sleep 2
( time ( pv -i 0.1 -cN in0 < "${f}" |
LC_ALL=C perl -wnl -e '$.== 133668997 && print && exit;'
) ) | mawk 'BEGIN { print } END { print _ } NR' ;
fg: no current job
fg: no current job
7.58GiB 0:00:28 [ 275MiB/s] [============>] 100%
148,110,134 8,134,435,629 8,134,435,629 <<<< rows, chars, and bytes
count as reported by gnu-wc
in0: 5.45GiB 0:00:07 [ 701MiB/s] [=> ] 71%
( pv -i 0.1 -cN in0 < "${f}" | LC_ALL=C mawk2 '_{exit}_=NR==+__' FS='^$' ; )
6.22s user 2.56s system 110% cpu 7.966 total
77.37219=195591955519519519559551=0x296B0FA7D668C4A64F7F=
in0: 5.45GiB 0:00:17 [ 328MiB/s] [=> ] 71%
( pv -i 0.1 -cN in0 < "${f}" | LC_ALL=C perl -wnl -e ; )
14.22s user 3.31s system 103% cpu 17.014 total
77.37219=195591955519519519559551=0x296B0FA7D668C4A64F7F=
我可以用perl5.36甚至perl-6重新运行测试,如果你认为这会有所不同(也没有安装)
7.966秒(mawk2)与17.014秒(perl 5.34)
在这两者之间,后者是前者的两倍多,显然哪一种在ASCII文件中获取单行数据确实更快。
This is perl 5, version 34, subversion 0 (v5.34.0) built for darwin-thread-multi-2level
Copyright 1987-2021, Larry Wall
mawk 1.9.9.6, 21 Aug 2016, Copyright Michael D. Brennan
您也可以使用Perl实现这一点:
perl -wnl -e '$.== NUM && print && exit;' some.file