我想通过这样格式化的日志文件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}
圣多美和普林西比:
您可以匹配数字并用该值替换:
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}'