【问题标题】:How to print lines only if next line is not matching using sed or awk仅当使用 sed 或 awk 不匹配下一行时如何打印行
【发布时间】:2021-09-05 01:16:23
【问题描述】:

我在日志文件中有以下模式,其中“开始”在下一行以“结束”结束。我希望仅在下一行模式与“结束”不匹配时打印,即打印所有未结束的开始。

$ egrep AccountResource testlog.txt|egrep "Starts|Ends"
05:20:34.949 INFO  c.b.h.r.rest.Account - AccountResource for account:12345 - Starts
05:20:45.863 INFO  c.b.h.r.rest.Account - AccountResource () - Ends
05:20:46.274 INFO  c.b.h.r.rest.Account - AccountResource for account:12345 - Starts
05:20:46.360 INFO  c.b.h.r.rest.Account - AccountResource () - Ends
05:22:21.703 INFO  c.b.h.r.rest.Account - AccountResource for account:12345 - Starts
05:22:22.680 INFO  c.b.h.r.rest.Account - AccountResource for account:5678 - Starts
05:52:48.578 INFO  c.b.h.r.rest.Account - AccountResource for account:5678 - Starts
05:52:50.673 INFO  c.b.h.r.rest.Account - AccountResource () - Ends
05:52:50.937 INFO  c.b.h.r.rest.Account - AccountResource for account:12345 - Starts
05:52:50.977 INFO  c.b.h.r.rest.Account - AccountResource () - Ends
06:09:35.951 INFO  c.b.h.r.rest.Account - AccountResource for account:5678 - Starts
06:09:36.409 INFO  c.b.h.r.rest.Account - AccountResource () - Ends
06:09:36.690 INFO  c.b.h.r.rest.Account - AccountResource for account:5678 - Starts
06:09:36.720 INFO  c.b.h.r.rest.Account - AccountResource () - Ends

下面是预期的输出

05:22:21.703 INFO  c.b.h.r.rest.Account - AccountResource for account:12345 - Starts
05:22:22.680 INFO  c.b.h.r.rest.Account - AccountResource for account:5678 - Starts

【问题讨论】:

    标签: linux shell awk sed


    【解决方案1】:

    这可能对你有用(GNU sed):

    sed 'N;/Starts\n.*Ends$/d;P;D' file
    

    一次处理两行。

    如果第一个以Starts 结尾,第二个以Ends 结尾,则删除两者。

    否则打印/删除第一个并重复。

    【讨论】:

      【解决方案2】:

      使用您展示的示例,请尝试关注awk 代码。

      awk '
      !/AccountResource/{ next      }
      /AccountResource.*Starts$/{
        if(found && val){ print val }
        found=1
        val=$0
      }
      /AccountResource.*Ends$/{
        found=0
        val=""
      }
      '  Input_file
      

      说明:为上述添加详细说明。

      awk '                              ##Starting awk program from here.
      !/AccountResource/{ next      }    ##If a line does not contain AccountResource move cursor to next line.
      /AccountResource.*Starts$/{        ##Checking condition if line contains AccountResource and ends with Starts then do following.
        if(found && val){ print val }    ##If found and val both are SET then print val.
        found=1                          ##Setting found to 1 here.
        val=$0                           ##Setting val to current line here.
      }
      /AccountResource.*Ends$/{          ##Checking condition if line contains AccountResource and ends with Ends then do following.
        found=0                          ##Set found to 0 here.
        val=""                           ##Nullify val here.
      }
      '  Input_file                      ##Mentioning Input_file name here.
      

      【讨论】:

      • @Ibrahim Patel,如果我的回答对您有帮助,请告诉我?谢谢。
      【解决方案3】:

      您可以使用单个 awk 来完成这项工作:

      awk '!/AccountResource/{next} NR == nl && $NF!="Ends" {print p} $NF=="Starts" {p=$0; nl=NR+1}' testlog.txt
      
      05:22:21.703 INFO  c.b.h.r.rest.Account - AccountResource for account:12345 - Starts
      05:22:22.680 INFO  c.b.h.r.rest.Account - AccountResource for account:5678 - Starts
      

      更易读的版本:

      awk '
      !/AccountResource/ {next}
      NR == nl && $NF != "Ends" {print p}
      $NF == "Starts" {
         p = $0
         nl = NR+1
      }' testlog.txt
      

      【讨论】:

      • 哇,非常感谢@anubhava。它像冠军一样工作。我想详细学习sed和awk,请问哪里可以得到详细的培训?
      • @IbrahimPatel 请参阅 stackoverflow.com/tags/sed/infostackoverflow.com/tags/awk/info 了解学习资源
      • 对于 awk:Effective Awk Programming,第 5 版,作者:Arnold Robbins
      猜你喜欢
      • 2013-07-28
      • 2010-12-16
      • 2020-08-16
      • 2017-04-30
      • 2016-08-15
      • 1970-01-01
      • 1970-01-01
      • 2011-07-20
      相关资源
      最近更新 更多