linux 具尾带尖

bsxbgnwa  于 5个月前  发布在  Linux
关注(0)|答案(5)|浏览(80)

我正在努力与这个awk代码应该模仿tail命令

num=$1;
{
    vect[NR]=$0;
    
}
END{
    for(i=NR-num;i<=NR;i++)
            print vect[$i]
}

字符串
所以我在这里试图实现的是一个由awk/模拟的tail命令,例如,考虑cat somefile | awk -f tail.awk 10应该打印文本文件的最后10行,有什么建议吗?

vcirk6k6

vcirk6k61#

所有这些答案都存储了 * 整个 * 源文件。这是一个可怕的想法,会破坏更大的文件。
这里有一个只存储要输出的行数的快速方法(注意,更高效的tail总是更快,因为它不会读取整个源文件!):

awk -vt=10 '{o[NR%t]=$0}END{i=(NR<t?0:NR);do print o[++i%t];while(i%t!=NR%t)}'

字符串
更清晰(code golf更少):

awk -v tail=10 '
  {
    output[NR % tail] = $0
  }
  END {
    if(NR < tail) {
      i = 0
    } else {
      i = NR
    }
    do {
      i = (i + 1) % tail;
      print output[i]
    } while (i != NR % tail)
  }'


易读代码的解释:
这使用modulo operator来存储所需数量的元素(tail变量)。当每一行被解析时,它都存储在旧数组值的顶部(因此第11行存储在output[1]中)。
END节将增量变量i设置为零(如果我们得到的行数少于预期的行数)或行数,这告诉我们从哪里开始调用保存的行。然后我们按顺序打印保存的行。当我们返回到第一个值时(在我们打印完它之后),循环结束。
如果您不关心是否需要空白行来填充请求的数字,可以将if/else节(或者在我的golfed示例中的ternary clause)替换为i = NRecho "foo" |awk -vt=10 …在带有“foo”的行之前有九个空白行)。

7qhs6swi

7qhs6swi2#

for(i=NR-num;i<=NR;i++)
    print vect[$i]

字符串
$表示一个位置参数。只使用普通的i

for(i=NR-num;i<=NR;i++)
    print vect[i]


对我有效的完整代码是:

#!/usr/bin/awk -f
BEGIN{
        num=ARGV[1];
        # Make that arg empty so awk doesn't interpret it as a file name.
        ARGV[1] = "";
}
{
        vect[NR]=$0;
}
END{
        for(i=NR-num;i<=NR;i++)
                print vect[i]
}


您可能应该向END添加一些代码来处理NR < num的情况。

2exbekwf

2exbekwf3#

您需要将-v num=10添加到awk命令行以设置num的值。并在最后一个循环中从NR-num+1开始,否则您将以num+1行输出结束。

kqlmhetl

kqlmhetl4#

这可能对你有用:

awk '{a=a b $0;b=RS;if(NR<=v)next;a=substr(a,index(a,RS)+1)}END{print a}' v=10

字符串

00jrzges

00jrzges5#

tail实际上取决于两个完全不同的场景:
1.从管道进来,是的,遵循其他人提到的标准arr[ NR % tail_n ]方法。
1.作为一个固定的文件,(或者任何“可搜索”的虚拟设备),特别是如果文件很大,并且您正在寻找的#行很大,那么在前面做一个快速的wc -l并跳过所有的临时数组存储是值得的:

( time ( mawk2 -v ___='3.14159 %' 'BEGIN { 

    index(__ = ARGV[ARGC-!_],_ = "\47") && 
     gsub(_,(_ "\\" _)_, __)

     (_ = "LC_ALL=C gwc -l "(_ __)_) | getline
     close(_)

     printf("\f\f\t %d...\f\f\n",
           ___ = int(((_ = 100) - ___) * $1 /_)) >>("/dev/stderr")

     FS = RS } ___ < NR' "$f" ) | pv ) | xxh128sum | gcat -b ;

  sleep 4;

 ( time ( LC_ALL=C  gtail -n 4654474 "$f" ) | pv ) | xxh128sum | gcat -b
 out9: 1.39GiB 0:00:07 [ 193MiB/s] [ 193MiB/s] [ <=> ]
( mawk2 -v ___='3.14159 %' "$f" )  

 5.49s user 1.86s system 99% cpu 7.370 total

 1  607efeee007a7e50cc06ce287a82e78f  stdin
( LC_ALL=C  gtail -n 4654474 "$f" ; )  

 3.71s user 6.12s system 123% cpu 7.950 total

 1  607efeee007a7e50cc06ce287a82e78f  stdin

根据文件的总大小与行计数的比率,tail的速度是awk-tail的1. 0倍到2. 5倍,特别是对于固定文件而不是管道。

相关问题