3

我有一个测试文件:

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

现在我也想做同样的事情,但是命令system():

$ awk '{if( NR > (system("wc -l < file")-4) ) print}' file
8 
1 
8 
2 
8 
3 
8 
4 
8 
5 
8 
6 
8 
7 
8 
8 
userpc@userpc-desktop:

如何改进最后一个命令系统()?我还想打印文件的最后 4 行。感谢您的帮助。

4

7 回答 7

14

不需要awk,使用tail

$ tail -4 your_file
于 2012-09-22T19:16:43.910 回答
9

awk这绝对不是正确的工具。这样做很常见:sed '1{N;N;N;}; N; D; $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'

基本上,您跟踪看到的最后四行,并在到达文件末尾时将它们全部打印出来。您可以通过以下方式变得更加晦涩和高效:

awk '{a[++i%4]=$0} END {print a[++i%4],a[++i%4],a[++i%4],a[++i%4]}' OFS='\n'

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

于 2012-09-22T20:05:24.057 回答
6

一种使用方式GNU awk

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

结果:

5
6
7
8
于 2012-09-23T04:36:18.837 回答
5

如果您只是想要一种机制来改进您对wcinside的使用system,请尝试:

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

在 awk 中做更多的事情;

awk 'NR==1{ c="wc -l < " FILENAME; c | getline count } NR > count-4' input

这使用 NR==1 而不是 BEGIN,因为 FILENAME 未在 BEGIN 块内定义。请注意,这些都system不能在 awk 中使用,因为没有从 获取输出的好方法system,但是您可以做一些丑陋的事情,例如:

awk 'NR==1 { system( "wc -l > tmpfile < " FILENAME ); getline count < "tmpfile" }
    NR > count - 4' input

我不能足够强调这仅仅是一个学术练习。不要为此使用 awk!

于 2012-09-22T21:02:19.667 回答
2

tail是正确的工具,但如果你想在 awk 中看到它:

awk '{b=b RS $0} b~/(\n.*){4}/{sub(/[^\n]*\n/,"",b)} END{print b}'
  1. 将行追加到缓冲区,用换行符分隔;
  2. 如果缓冲区中有 4 个换行符,则从中删除第一行;
  3. 最后,打印缓冲区。
于 2013-06-24T23:30:23.237 回答
2

tac这是使用and的另一种方式awk

$ tac file | awk 'NR==5{exit}1' | tac
5
6
7
8
  • tac反转文件。
  • awk打印前 4 行并退出(如果您的文件非常大,则可以使用)
  • tac再次反转文件
于 2014-05-23T06:30:41.003 回答
1
awk 'NR==5, NR==8{print NR} file

从第 5 行到第 8 行打印

于 2014-01-05T21:10:02.290 回答