【问题标题】:awk find the last match and print the next N linesawk 找到最后一个匹配并打印接下来的 N 行
【发布时间】:2014-11-02 11:54:13
【问题描述】:

我有一个包含以下内容的日志文件:

Date: 2014-09-07
Price: 1.35
Amount: 20
ProcessedBy: Bill

Some other contents

Date: 2014-09-08
Price: 10.1
Amount: 15
ProcessedBy: Alice

Some other contents

Date: 2014-09-09
Price: 100
Amount: 2.6
ProcessedBy: Boss

Some other contents

我想用awk查找最后一个“日期”,并打印以下三行。

Date: 2014-09-09
Price: 100
Amount: 2.6
ProcessedBy: Boss

我使用代码:

awk '/Date/ {x=NR}; END{NR>=x && NR<=x+3} LOG_FILE

但是,我似乎无法将 NR 输出放在 END 之后。

如何在最后一场比赛之后得到以下N行?

感谢您的关注!

【问题讨论】:

    标签: regex bash awk


    【解决方案1】:
    $ awk  '/^Date:/ {c=1; a=$0;next} c<=3{c=c+1;a=a"\n"$0}END{print a}' LOG_FILE
    Date: 2014-09-09
    Price: 100
    Amount: 2.6
    ProcessedBy: Boss
    

    一次取一段代码:

    • /^Date:/ {c=1; a=$0;next}

      每次遇到以Date:开头的行时,将计数器c赋值为1,将该行赋值给变量a,然后跳到下一行

    • c&lt;=3{c=c+1;a=a"\n"$0}

      如果计数器小于或等于三,则递增计数器并将新行保存到变量 a 的末尾。

    • END{print a}

      打印最后一次看到的a的值。

    本题第二版代码

    $ awk -v RS=  '/^Date:/ {a=$0} END{print a}' LOG_FILE
    Date: 2014-09-09
    Price: 100
    Amount: 2.6
    ProcessedBy: Boss
    

    一次取一段代码:

    • -v RS=

      awk 将其输入划分为“记录”。这可以通过将记录分隔符 RS 设置为空行来实现。 (对于 GNU awk,一个空的 RS 匹配一个空行。对于其他版本的 awk,您可能需要做一些不同的事情。)

    • /^Date:/ {a=$0}

      每次遇到以Date:开头的记录时,都会将其保存在变量a中。

    • END{print a}

      在运行结束时,将打印最后一次看到的 a 值。

    此问题第一版的代码

    $ awk -v RS=  'END{print $0}' LOG_FILE
    Date: 2014-09-09
    Price: 100
    Amount: 2.6
    ProcessedBy: Boss
    

    【讨论】:

    • 感谢您的详细解释!使用 RS= 是一个不错的选择,但实际上我的日志文件包含一些可能与当前数据提取无关的其他内容(之前我没有描述清楚,抱歉)。我想找到最后一次出现的“日期”,并打印接下来的三行。但是我过去查找最后一个“日期”并使用“结束”打印的方式不起作用。您能建议我如何实现这一目标吗?
    • 非常感谢您的详细解释和多个回答!
    【解决方案2】:

    你也可以试试 perl,

    $ perl -0777pe 's/.*?\n(Date:(?:(?!Date:).)*)$/\1/s' file
    Date: 2014-09-09
    Price: 100
    Amount: 2.6
    ProcessedBy: Boss
    

    【讨论】:

      【解决方案3】:

      你可以使用这个 awk:

      awk -v RS= '/^Date:/{data=$0} END{print data}' file
      Date: 2014-09-09
      Price: 100
      Amount: 2.6
      ProcessedBy: Boss
      

      【讨论】:

        【解决方案4】:

        您可以尝试在两个模式之间打印线条,如下所示

        awk '/StartPattern/,/EndPattern/' FileName 
        

        对你来说,它可以像这样工作

        awk '/2014-09-09/,/ProcessedBy/' FileName
        

        【讨论】:

        • 感谢您的回答。有时我不知道确切的模式是什么(例如日志中记录的日期),因此我必须找到最后一次出现:)
        【解决方案5】:

        您不能将NR 放入END,但您可以这样做:

        awk '{a[NR]=$0} /^Date/ {f=NR} END {for (i=f;i<f+4;i++) print a[i]}'
        Date: 2014-09-09
        Price: 100
        Amount: 2.6
        ProcessedBy: Boss
        

        它将所有行存储在数组a中,然后将最后一个Date存储在f中。
        END 块中,在最后一个Date 命中后从数组a 打印四行

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-01-09
          • 2019-03-28
          • 2014-04-04
          • 1970-01-01
          • 2020-06-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多