将多行转换为一条并从中提取列

时间:2018-11-01 16:08:31

标签: bash perl awk

我有xml格式的日志流(来自名为mytool的促销工具),我需要使它们在一行中看起来可读。我在此节点上没有xml解析工具,因此最终使用了perl和awk。

我设法获得了期望的结果,但希望将管道/ awk / perl的数量减少到最小。

输入流示例:

./mytool

<ALERT>
   <Time>2018-10-24T16:03:00.128-05:00</Time>
   <Alert>0;2018-10-24T16:02:37.739-05:00;NODE_LOCATION=19;11193;ID=5636122;Temp is on critical range;000;CRITICAL;Recovery=Shutting down the node;100</Alert>
</ALERT>



<ALERT>
   <Time>2018-10-24T16:03:03.053-05:00</Time>
   <Alert>0;2018-10-24T16:02:40.264-05:00;NODE_LOCATION=17;11293;ID=5636124;Temp is on Major range;000;MAJOR;Recovery=Shutdown the node or it will auto shutdown,processes stopped;99</Alert>
</ALERT>

我想要的结果:

2018-10-24T16:02:37.739-05:00  5636122 Temp is on critical range CRITICAL Shutting down the node
2018-10-24T16:02:40.264-05:00  5636124 Temp is on Major range MAJOR Shutdown the node or it will auto shutdown,processes stopped

我用来获取结果的当前命令:

./mytool | perl -000 -lnpe 's/<.*?>|NODE_LOCATION=|Recovery=|ID=//g' | awk -vRS= '{$1=$1}1' |awk -F';' '{print $2,$$4,$5,$6,$8,$9}'

2018-10-24T16:02:37.739-05:00  5636122 Temp is on critical range CRITICAL Shutting down the node
2018-10-24T16:02:40.264-05:00  5636124 Temp is on Major range MAJOR Shutdown the node or it will auto shutdown,processes stopped

注意:请理解,使用awk perl并不是处理xml的最佳方法,但这是可能的最佳方法,因此必须妥协。

3 个答案:

答案 0 :(得分:3)

请尝试以下操作(考虑到您的脚本输出始终与显示的输出处于相同模式)。

your_command | awk -F"[><]" '
/<Time>/{
  val=$3
  next
}
/<Alert>/{
  split($3,array,";")
  sub(/.*=/,"",array[5])
  sub(/Recovery=/,"",array[9])
  print val,array[5],array[6],array[8],array[9]
}' 

答案 1 :(得分:2)

mytool | perl -nE 'if(/<Alert>/){s/Recovery=|ID=//g; say join " ",(split/;/)[1,4,5,7,8]}'

如您的示例所示,假设您的XML每行只有一对标记对,那么上述方法将起作用。

答案 2 :(得分:1)

如果需要,您可以在Perl中完成所有操作。避免使用管道连接到awk。例如:

mytool | perl -nE '
  m{<Alert>(.*?)</Alert>} and do {($line = $1) =~ s/NODE_LOCATION=|Recovery=|ID=//g; 
  @F = split /;/, $line; say join " ", @F[1,3,4,5,6,7,8]}'