我正在尝试使用Linux中的sed,awk,paste命令将特定日志文件转换为CSV文件,以便能够使用gnuplot或MS Excel绘制它。但是,我无法以我想要的方式做到这一点。以下是示例日志文件:
Feb 15 13:57:08 Program1: The pool size: 100 [High: 80 Norm: 20 Low: 0]
Feb 15 13:58:53 Program1: The pool size: 100 [High: 0 Norm: 100 Low: 0]
Feb 15 13:58:54 Program3: The pool size: 200 [High: 0 Norm: 200 Low: 0]
Feb 15 13:58:56 Program4: The pool size: 100 [High: 0 Norm: 100 Low: 0]
Feb 15 13:58:58 Program1: The pool size: 200 [High: 0 Norm: 200 Low: 0]
Feb 15 13:58:59 Program5: The pool size: 300 [High: 100 Norm: 200 Low: 0]
Feb 15 13:59:05 Program1: The pool size: 100 [High: 0 Norm: 100 Low: 0]
Feb 15 14:00:11 Program2: The pool size: 100 [High: 0 Norm: 100 Low: 0]
Feb 15 14:00:12 Program2: The pool size: 100 [High: 0 Norm: 100 Low: 0]
Feb 15 14:00:13 Program1: The pool size: 200 [High: 0 Norm: 200 Low: 0]
Feb 15 14:00:16 Program4: The pool size: 100 [High: 0 Norm: 100 Low: 0]
Feb 15 14:00:17 Program2: The pool size: 100 [High: 50 Norm: 50 Low: 0]
Feb 15 14:02:28 Program5: The pool size: 100 [High: 0 Norm: 100 Low: 0]
Feb 15 14:02:31 Program1: The pool size: 100 [High: 0 Norm: 100 Low: 0]
Feb 15 14:11:01 Program1: The pool size: 100 [High: 0 Norm: 100 Low: 0]
我正在尝试将上述数据转换为CSV文件,以便在特定时间点获取数据。我期望的输出CSV应采用以下格式:
TimeStamp,Program1_Total,Program1_High,Program1_Norm,Program1_Low,Program2_Total,Program2_High,Program2_Norm,Program2_Low,Program3_Total,Program3_High,Program3_Norm,Program3_Low,Program4_Total,Program4_High,Program4_Norm,Program4_Low
Feb 15 13:57:08,100,80,20,0,0,0,0,0,0,0,0,0,0,0,0,0
Feb 15 13:58:53,100,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0
...
...
我尝试了什么?
我尝试了grepping特定程序,并按以下方式创建特定于该程序的单独的较小文件:
grep "Program1" sample.log > Program1.log
grep "Program2" sample.log > Program2.log
我尝试使用paste命令加入它们。但是,我无法弄清楚如何以更好的方式处理这些时间戳。
任何帮助都将受到高度赞赏。提前谢谢。
答案 0 :(得分:1)
使用空格作为分隔符来使用剪切,然后仅保留所需的字段。完成后,使用sed用逗号替换空格。
cut -d ' ' -f 1,2,3,8,10,12,14 && sed 's/ /,/g'
通过使用while ... read循环,您可以在每一行中迭代它。
答案 1 :(得分:1)
我认为我为你的任务找到了一个单线程解决方案,它只使用shell和awk
,但是请注意,它根本不是很漂亮,你需要事先将标题添加到输出文件中:
echo "TimeStamp,P1_Total,P1_High,P1_Norm,P1_Low,P2_Total,P2_High,P2_Norm,P2_Low,P3_Total,P3_High,P3_Norm,P3_Low,P4_Total,P4_High,P4_Norm,P4_Low,P5_Total,P5_High,P5_Norm,P5_Low" >> final_output.txt
for i in `seq 1 5`
do
l=$((i-1))
r=$((5-i))
awk -v left_padd=${l} -v right_padd=${r} -v nb=${i} '{gsub(/]/, "", $14)} {if ($4 ~ "Program" nb) {printf $1" "$2" "$3", "; for(a=0;a<left_padd;a++) printf "0,\t 0,\t 0,\t 0,\t "; printf $8",\t "$10",\t "$12",\t "$14",\t "; for(b=0;b<right_padd;b++) printf "0,\t 0,\t 0,\t 0,\t "; print "\n"} }' sample.log
done >> final_output.txt
***请注意,您必须将5
中的seq 1 5
更改为输出文件中您希望拥有的Program#
条目数,我使用5
就像你的例子那样。此外,您还需要将5
中的r=$((5-i))
更改为相同的值。
说明:
for
循环每次都会传递文件以搜索Program#
使用awk
输入。l
变量计算左侧应添加的0个值
你的桌子。 r
变量与l
值相同,只添加0值
在右边。nb
变量存储Program #
,因此awk
部分知道
它应该在输入文件中查找哪些行。awk
仅打印出您在输入中要求的值
每个Program#
条目的文件以及前一个和尾随的文件
表中其他条目的0
值(每个0
为Program#
个}。编辑:
我使用\t
来分隔awk
中的值,因此更容易阅读,但您可以删除它,因此您只能使用逗号分隔值。
出于同样的原因,我还将答案从Program#_Total
更改为P#_Total
。
*我确实意识到这根本不是最优的,因为每个Program#
条目都会多次解析文件,你还需要在输出文件中自己添加标题,但这是我能做的最好的想出来。
答案 2 :(得分:1)
如果Perl在选项中,那么:
CASE((CAST...
顺便说一句,看起来您的所需结果中不包括Program5。如果要包含它,只需将第二行中的数字15修改为19。