【问题标题】:AWK: Printing lines after they were already processedAWK:在处理完后打印行
【发布时间】:2017-02-02 12:04:19
【问题描述】:

我有一个简单的文件,由我的 awk 脚本处理:

AAAAA BBBBBB
CCCCC DDDDDD
EEEEE FFFFFF
GGGGG HHHHHH
IIIII JJJJJJ

首先,我想打印出最后一行,所以我从

#!/usr/bin/awk
{if (NR==5){print $0;}}

因此得到IIIII JJJJJJ

现在我想在打印出第 5 行后打印第 2 行。所以我把我的脚本改成这样:

#!/usr/bin/awk
{if (NR==5){print $0; NR=2;}
if (NR==2){print $0;}

但在这种情况下,这是一个永无止境的循环。如何先打印第 5 行,然后再打印第 2 行而不再次打印第 5 行?

为清晰起见,预期输出:

IIIII JJJJJJ
CCCCC DDDDDD

【问题讨论】:

  • 最终脚本中没有永无止境的循环。设置 NR=2 不会告诉 awk 重新开始读取第 2 行的输入,它只是将变量 NR 设置为值 2 直到读取下一行,第 6 行,此时 NR 变为6。此外,您还缺少基本的 awk condition { action } 语法 - awk 不是 C。请阅读 Arnold Robbins 的《Effective Awk Programming, 4th Edition》一书。

标签: awk


【解决方案1】:

这个怎么样:

awk '{if (NR==2){x=$0} else if (NR==5) {y=$0}} END {print y; print x}' input 

当我们逐行扫描文件时,我们将感兴趣的行存储在一些变量中,然后在最后打印它们。

这里有一个更简单的替代方案:

awk '{if (NR==2){x=$0} else if (NR==5) {print $0; print x}}' input 

这仅将第 2 行存储在变量中。当我们到达第 5 行时,我们打印它,然后我们从变量中打印第 2 行。

编辑:正如 William Pursell 指出的那样,编写上述代码的更惯用的方法是

awk 'NR==2 {x=$0} NR==5 {y=$0} END {print y; print x}' input 

awk 'NR==2 {x=$0} NR==5 {print $0; print x}' input 

【讨论】:

  • 哦,你是用变量做的。这样就可以了。谢谢
  • 更惯用的做法awk 'NR==2 {x=$0} NR==5{print $0; print x; }
  • @WilliamPursell 你说得对,我只提供了一个让 OP 更容易理解的答案。
  • awk 'NR==2{s=$0} NR==5{print $0 ORS s}' file。不要让 OP 认为您需要为每一行输出单独的 print 语句。如果文件很大,请在 } 之前添加 ;exit
【解决方案2】:

通过反转输入文件(逐行)的替代解决方案.. 需要知道输入文件中的行数并相应地调整NR

$ tac ip.txt | awk 'NR==1 || NR==4'
IIIII JJJJJJ
CCCCC DDDDDD

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-07
    • 2020-09-03
    • 1970-01-01
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-12
    相关资源
    最近更新 更多