获取最后一行匹配的第一个字

我想通过这样格式化的日志文件parsing:

INFO: Successfully received REQUEST_ID: 1111 from 164.12.1.11 INFO: Successfully received REQUEST_ID: 2222 from 164.12.2.22 ERROR: Some error INFO: Successfully received REQUEST_ID: 3333 from 164.12.3.33 INFO: Successfully received REQUEST_ID: 4444 from 164.12.4.44 WARNING: Some warning INFO: Some other info 

我需要一个输出4444的脚本。因此,从包含模式^。* REQUEST_ID的最后一行^。* REQUEST_ID之后提取下一个单词。

我到目前为止:

 ID=$(sed -n -e 's/^.*REQUEST_ID: //p' $logfile | tail -n 1) 

对于匹配模式匹配的行,它将删除匹配匹配的所有文本,从而仅留下匹配后的文本并将其打印出来。 然后我尾巴得到最后一行。 如何做到这一点,只打印第一个字?

有没有一个更有效的方法来做到这一点,然后pipe道尾巴?

用awk:

 awk ' $4 ~ /REQUEST_ID:/{val=$5} END {print val} ' file.csv 

$4 ~ /REQUEST_ID:/ :匹配字段#4匹配REQUEST_ID:

{val=$5} :将字段5的值存储在变量val中。

END {print val} :在关闭文件时,打印存储的最后一个值。

我使用了正则表达式匹配来允许字符串有一些变化,但是却得到了一个匹配。 比较宽松的比赛将是(在任何地方比赛):

 awk ' /REQUEST_ID/ {val=$5} END {print val} ' file.csv 

如果你看重(或者需要)比鲁棒性更高的速度,那就用(需要引用):

 awk ' $4 == "REQUEST_ID:" {val=$5} END {print val} ' file.csv 

用GNU sed:

 sed -nE 's/.* REQUEST_ID: ([0-9]+) .*/\1/p' | tail -n 1 

输出:

 4444

用GNU grep:

 grep -Po 'REQUEST_ID: \K[0-9]+' file | tail -n 1 

输出:

 4444

-P :将PATTERN解释为Perl正则表达式。

-o :仅打印匹配行的匹配(非空)部分,每个这样的部分位于单独的输出行中。

\K :放弃内部记录之前的所有内容。

 sed '/^.*REQUEST_ID: \([0-9]\{1,\}\) .*/ {s//\1/;h;} $!d x' ${logfile} 
  • posix版本
  • 打印一个空行,如果没有发生,下一个字(假设这是一个数字)

圣多美和普林西比:

  • 如果行包含REQUEST_ID
    • 提取下一个数字
    • 把它放在缓冲区
  • 如果不是结束,则删除当前内容(并循环到下一行)
  • 加载保持缓冲区(并打印结束循环的行)

您可以匹配数字并用该值替换:

 sed -e 's/^.*REQUEST_ID: \([0-9]*\).*$/\1/g' $logfile 

在行和列相交处的打印字段。

 awk 'FNR == 5 {print $5}' file 4444 

另一个awk替代方案,如果你不知道搜索词的位置。

 tac file | awk '{for(i=1;i<NF;i++) if($i=="REQUEST_ID:") {print $(i+1);exit}}' 

然而,另一个没有循环

 tac file | awk -vRS=" " 'n{print;exit} /REQUEST_ID:/{n=1}'