得到最后一行的第一个匹配词

时间:2015-08-25 22:46:10

标签: linux awk sed

我想解析一个格式如下的日志文件:

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)

对于匹配模式匹配的行匹配,它会删除与匹配匹配的所有文本,从而仅在匹配后保留文本并打印它。然后我拖尾它以获得最后一行。该怎么做使它只打印第一个单词?

是否有一种更有效的方法可以实现这一目标,然后将其传送到尾部?

6 个答案:

答案 0 :(得分:4)

使用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

答案 1 :(得分:3)

使用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:从内部记录中删除该点之前的所有内容。

答案 2 :(得分:2)

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

<强>普林西:

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

答案 3 :(得分:1)

您可以匹配该号码并替换为该值:

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

答案 4 :(得分:0)

打印行和列相交的字段。

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

答案 5 :(得分:0)

如果您不知道搜索词的位置,则为另一个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}'