Awk-打印文件的最后4行

Awk-打印文件的最后4行,awk,Awk,我有一个测试文件: 1 2 3 4 5 6 7 8 此命令打印文件的最后4行: $ awk 'BEGIN{"wc -l < file" | getline b}{if(NR>b-4) print}' file 5 6 7 8 userpc@userpc-desktop $awk'BEGIN{“wc-lb-4)print}文件 5. 6. 7. 8. userpc@userpc-桌面 现在我想做同样的事情,但是命令系统(): $awk'{if(NR>(系统(“wc-l

我有一个测试文件:

1
2
3
4
5
6
7
8
此命令打印文件的最后4行:

$ awk 'BEGIN{"wc -l < file" | getline b}{if(NR>b-4) print}' file
5 
6 
7 
8 
userpc@userpc-desktop
$awk'BEGIN{“wc-lb-4)print}文件
5.
6.
7.
8.
userpc@userpc-桌面
现在我想做同样的事情,但是命令系统():

$awk'{if(NR>(系统(“wc-l
如何改进上一个命令系统()?我还想打印文件的最后4行。
谢谢您的帮助。

无需awk,请使用
tail

$ tail -4 your_file

awk
绝对不是解决这个问题的合适工具。通常会这样做:
sed'1{N;N;N;};ND$p'
,您可以使用awk执行类似的操作:

awk '{for( i=0;i<3;i++) a[i]=a[i+1];a[3]=$0} END {print a[0],a[1],a[2],a[3]}' OFS='\n'

但是,真的,你为什么要这样做呢?

如果你只是想在
系统中改进
wc
的使用,请尝试:

awk 'NR > count-4' count=$( wc -l < file ) file

我再怎么强调也不为过,这仅仅是一项学术活动。不要为此使用awk

单向使用GNU awk

awk '{ array[NR]=$0 } END { for (i=NR-3; i<=NR; i++) print array[i] }' file.txt

tail
是正确的工具,但如果您希望看到它在Awk中完成:

awk '{b=b RS $0} b~/(\n.*){4}/{sub(/[^\n]*\n/,"",b)} END{print b}'
  • 将行追加到缓冲区,以换行符分隔
  • 如果缓冲区中有4个换行符,则从中删除第一行
  • 最后,打印缓冲区

  • 从第5行打印到第8行

    这里是使用
    tac
    awk
    的另一种方法:

    $ tac file | awk 'NR==5{exit}1' | tac
    5
    6
    7
    8
    
    • tac
      以反转文件
    • awk
      打印前4行并退出(如果您的文件非常大,这很好)
    • tac
      再次反转文件

    谢谢你,回答得很好,但问题是关于awk和最后一个命令。如果存在简单的解决方案,为什么会比较复杂?感谢解决方案的建议。一般情况下,一个实用的解决方案是将输出从tail传输到awk:tail-4文件| awk'{print}',print'可能是更有用的awk表达式。您为文件的每一行分叉一个
    wc
    ???像你这样的人是4GHz、具有64GB RAM的八核CPU的原因:-)哦,它不起作用,因为system()返回退出状态(在本例中为0->始终为真),而不是wc的输出。正如您所看到的,每行都会打印标准输出(“8”)。感谢您的澄清,但我仍然不知道如何改进命令系统()。这是一个很好的解决方案,但用于打印少量行。如果我打印更多的行,命令会更长。实际上,这是一个糟糕的解决方案!但是如果使用第二种形式和for循环,它的伸缩性会很好。ie
    awk'{a[++i%n]=$0}END{for(j=0;j)这个解决方案很好。但是我会等待改进我的第二个指挥系统的建议()。您评论中的解决方案将是正确的方式。原则与我的答案类似。但是,真的,您为什么要这样做?出于同样的原因,您需要文件的前4行。此示例指出了awk作为通用工具的局限性。感谢解决方案的建议。感谢解决方案的建议。从技术上讲,您仍在使用g awk,再加上另一个我认为可以接受和有用的工具——更容易记忆和打字。
    
    awk 'NR==1 { system( "wc -l > tmpfile < " FILENAME ); getline count < "tmpfile" }
        NR > count - 4' input
    
    awk '{ array[NR]=$0 } END { for (i=NR-3; i<=NR; i++) print array[i] }' file.txt
    
    5
    6
    7
    8
    
    awk '{b=b RS $0} b~/(\n.*){4}/{sub(/[^\n]*\n/,"",b)} END{print b}'
    
    awk 'NR==5, NR==8{print NR} file
    
    $ tac file | awk 'NR==5{exit}1' | tac
    5
    6
    7
    8