我一直在努力解决一些为 logstash 提取数据做准备的问题。我已经解决了相当一部分流程,但我想知道是否有更好的方法来实现这一点。基本上我需要转置以下内容:
title,device1,device2
01/01/2001 00:30,data.dev1.ts1,data.dev2.ts1
01/02/2002 01:00,data.dev1.ts2,data.dev2.ts2
12/01/2003 15:00,data.dev1.ts3,data.dev2.ts3
到
01/01/2001 00:30,device1,data.dev1.ts1
01/01/2001 00:30,device2,data.dev2.ts1
01/02/2002 01:00,device1,data.dev1.ts2
01/02/2002 01:00,device2,data.dev2.ts2
12/01/2003 15:00,device1,data.dev1.ts3
12/01/2003 15:00,device2,data.dev2.ts3
我目前正在做的是创建两个文档。一个包含每个时间戳的数据(test.data.csv),另一个包含每个时间戳的设备编号(test.dev.csv。本质上,这类似于 test.data.csv,只是复制了设备 ID 以替换数据)。然后,我在两个文件上运行以下 perl 代码以进行垂直转置:
perl -F, -lane '$s=shift @F;print "$s,$_" for @F' test.data.csv > test.data2.csv
perl -F, -lane '$s=shift @F;print "$s,$_" for @F' test.dev.csv > test.dev2.csv
然后我从数据文件中删除日期:
awk -F, '{print $2}' test.data2.csv test3.csv
合并文件:
awk -F, '{getline f1 <"test3.csv" ;print $1,$2,f1}' OFS=, test.dev2.csv > test4.csv
这是我的主要问题出现的地方。最后一个 awk 命令将顺利运行整个文件,除了最后一行。在上面的例子中,返回的最后一行是:
,2/01/2003 15:00,device2
而不是应该的那样:
12/01/2003 15:00,device2,data.dev2.ts3
您对为什么会发生这种情况有什么想法吗? 我没有使用 getline 选项得到最后一行的行为不同的内容吗?
我也乐意接受任何有关改进此工作流程的建议。我不喜欢将文件分开或为此创建两个输入文件。
答案1
你看起来工作很忙。
awk '
BEGIN {FS = OFS = ","}
NR == 1 {dev1 = $2; dev2 = $3; next}
{
print $1, dev1, $2
print $1, dev2, $3
}
' input
对于任意数量的设备,只需使用循环:
awk '
BEGIN {FS = OFS = ","}
NR == 1 {for (i=2; i<=NF; i++) device[i] = $i}
NR > 1 {for (i=2; i<=NF; i++) print $1, device[i], $i}
' input