【问题标题】:AWK print next line of match between matchesAWK 在匹配之间打印下一行匹配
【发布时间】:2015-02-05 21:57:06
【问题描述】:

假设我有包含以下数据的文件 test.txt:

.0
41
0.0
42
0.0
43
0.0
44
0.0
45
0.0
46
0.0
START
90
34
17
34
10
100
20
2056
30
0.0
10
53
20
2345
30
0.0
10
45
20
875
30
0.0
END
0.0
48
0.0
49
0.0
140
0.0

使用 AWK 如何在 START 和 END 之间打印 10 和 20 之后的行。 所以输出会是。

100
2056
53
2345
45
875

我能够得到 10 和 20 的行

awk '/START/,/END/ {if($0==10 || $0==20) print $0}' test.txt 

但是我如何获得下一行?

【问题讨论】:

    标签: awk


    【解决方案1】:

    我真的得到了我想要的东西

    awk '/^START/,/^END/ {if($0==10 || $0==20) {getline; print} }' test.txt
    

    【讨论】:

    • 另一种方式awk 'x;/START/,/END/{if(x||/^(10|20)$/)x=!x}' file
    • @JID 工作,但可读性较差。并且可以缩短一些^(1|2)0$
    • @Jotne ^(1|2)0$ 实际上会损害可读性,尽管您搜索的内容不太明显,尤其是在使用大量数字的情况下。
    【解决方案2】:

    awk 中的范围可以正常工作,但不如使用标志灵活。

    awk '/^START/ {f=1} /^END/ {f=0} f && /^(1|2)0$/ {getline;print}' file
    100
    2056
    53
    2345
    45
    875
    

    【讨论】:

    • 这将匹配其中包含 10 或 20 的任何内容,例如 100。
    • @JID 在您发表评论之前已修复 :)
    【解决方案3】:

    不要使用范围,因为它们会使琐碎的事情稍微简单一些,但当事情变得稍微复杂一点时,就需要完全重写或复制条件。

    除非是合适的应用程序并且您已阅读并完全理解 http://awk.info/?tip/getline,否则请勿使用 getline。

    让 awk 按设计读取您的行:

    $ cat tst.awk
    /START/  { inBlock=1 }
    /END/    { inBlock=0 }
    foundTgt { print; foundTgt=0 }
    inBlock && /^[12]0$/ { foundTgt=1 }
    
    $ awk -f tst.awk file
    100
    2056
    53
    2345
    45
    875
    

    如果您觉得有用,请随意使用单字符变量名并将其全部塞到一行中:

    awk '/START/{b=1} /END/{b=0} f{print;f=0} b&&/^[12]0$/{f=1}' file
    

    【讨论】:

    • 我实际上发现单行更容易理解。此外,虽然^[12]0$ 保存了一两个字符,但我发现 /^(10|20)$/ 可以更清楚地显示您要搜索的内容,尤其是在数字较大或有很多的情况下。
    • 我想的课程用马。我发现^[12]0$ 更清楚。哦,好吧。
    最近更新 更多