提前对文字墙表示歉意,不知道如何表示现有的数据结构。
我收到了从服务器每小时收集的大约一年的日志。
遗憾的是,修复数据收集脚本以使其按照他们希望的方式构建文件很容易,但我仍然需要转换数千个现有文件。我在这里遇到了一些困难,并怀疑这要么超出了我的能力,要么我在精神上让这条路变得比它必须的更加困难。
这是其中一次运行的基本迭代(每小时每 5 分钟运行一次)
2350
id pool type rid rset min max size used load
5 SUNWtmp_serverxd1z1 pset 1 SUNWtmp_serverxd1z1 104 104 104 0.00 6.25
4 SUNWtmp_serverxd1z2 pset 2 SUNWtmp_serverxd1z2 16 16 16 0.00 0.91
0 pool_default pset -1 pset_default 24 66K 24 0.00 1.74
id pool type rid rset min max size used load
5 SUNWtmp_serverxd1z1 pset 1 SUNWtmp_serverxd1z1 104 104 104 5.01 6.21
4 SUNWtmp_serverxd1z2 pset 2 SUNWtmp_serverxd1z2 16 16 16 0.97 0.91
0 pool_default pset -1 pset_default 24 66K 24 3.73 1.78
输出被截断,但它从前一个时间戳开始持续 50 行,直到下一个时间戳。
我不知道如何在块引用中显示数字,但每次运行都有 50 行长(它们全部组合成一个每天大约 14400 行的文件,每行前面的字段是日期从文件名派生。
这就是他们想要的样子。就空白而言,字段位置似乎并不重要,只是相对字段位置,包括显示为迭代到 2 的新字段“int”,但实际上只会每 50 行迭代一次(完整的数据收集运行),然后从 01 开始。
date hhmm int id pool type rid rset min max size used load
20121105 2350 01 5 SUNWtmp_serverxd1z1 pset 1 SUNWtmp_serverxd1z1 104 104 104 0.00 6.25
20121105 2350 01 4 SUNWtmp_serverxd1z2 pset 2 SUNWtmp_serverxd1z2 16 16 16 0.00 0.91
20121105 2350 01 0 pool_default pset -1 pset_default 24 66K 24 0.00 1.74
date hhmm int id pool type rid rset min max size used load
20121105 2350 02 5 SUNWtmp_serverxd1z1 pset 1 SUNWtmp_serverxd1z1 104 104 104 5.01 6.21
20121105 2350 02 4 SUNWtmp_serverxd1z2 pset 2 SUNWtmp_serverxd1z2 16 16 16 0.97 0.91
20121105 2350 02 0 pool_default pset -1 pset_default 24 66K 24 3.73 1.78
我已经尝试了一些 sed 和 awk oneliners,但悲伤地意识到我从来没有以任何比 1liners 可以处理的方式更复杂的方式操作文本,此时我看到这个文件需要比那更复杂的东西。
我尝试使用格式的示例:
gawk -vdate=$DATE -vtime=$TIME '{print date " " time $0 }' ./poolstat_original_format.txt
使用从文件名派生的日期和时间到这两个变量中。
我之前的 shell 脚本编写经验都与系统自动化和故障排除有关,从未有过如此多的文本移动的实际经验,所以如果这实际上是一个简单的问题,而我只是想太多了,那就太棒了,任何有用的评论都会受到赞赏。
我本想添加的附加信息但被取消了。
日期源自传入的文件名。 20121003-poolstat_serverxd1z0.txt 时间是每 50 行 4 位数字。
每次运行 poolstat 时,int 字段都需要迭代。详情请参阅下文。
总之,唯一需要更改的字段:
字段 1,8 位日期,源自文件名 IE:20121003-poolstat_serverxd1z0.txt 字段 2,文件内每 50 行的 4 位时间。字段 3 迭代计数,如下所示: 基于 4 位时间的第 3 和 4 位。 00-05-10-15-20-25-30-35-40-45-50-55 分钟跑步。
01-02-03-04-05-06-07-08-09-10-11-12 迭代。
剩下的只是打印出现有字段,将它们放在一行上,然后 awk (或其他)命令打印出其他 10 个字段,同时跟踪当前迭代。
为了让事情变得复杂,标题行中的字段还需要 3 个新字段:
日期 hhmm 整数
其余字段是 poolstat 提供的标头。
答案1
对我的评论问题持保留意见,这应该有效:
awk -v date=20121105 'NF == 0 {print; next;};
NF==15 && $2 == "id" {readvar=$1; for (i=1;i<15;i++) $i = $(i+1); NF=14; };
NF==14 { if (block<2) block++;
concatvars=$1; for (i=2;i<11;i++) concatvars=concatvars " " $i;
print "date hhmm int",concatvars,date,readvar,sprintf("%02d", block),"05"; };
NF==10 {readvar2=$7;
print $1,"pset 1",$1,$2,$3,$4,$5,$6,date,readvar,sprintf("%02d", block);};
NF==15 {
print readvar2,$1,"pset 2",$1,$2,$3,$4,$5,$6,date,sprintf("%02d", block),$7;
nextline=$8; for (i=9;i<15;i++) nextline=nextline " " $i; };
NF==1 {print nextline,$1}' inputfile
答案2
看起来您必须从块的开头获取时间,然后向此后的每一行添加一些字段。
根据您的描述,我不确定应该如何进行迭代
awk -v date=20121105 '
NF == 1 {time = $1; intv = intv%50 + 1; next}
$1 == "id" {print "date", "hhmm", "int", $0; next}
NF > 0 {$1 = date OFS time OFS sprintf("%02d", intv) OFS $1}
1
' file
如果您想让输出更漂亮,请将 awk 命令通过管道传递到column -t