shell脚本对文本文件数据结构进行一些文本操作并进行轻微的内容更改

shell脚本对文本文件数据结构进行一些文本操作并进行轻微的内容更改

提前对文字墙表示歉意,不知道如何表示现有的数据结构。

我收到了从服务器每小时收集的大约一年的日志。

遗憾的是,修复数据收集脚本以使其按照他们希望的方式构建文件很容易,但我仍然需要转换数千个现有文件。我在这里遇到了一些困难,并怀疑这要么超出了我的能力,要么我在精神上让这条路变得比它必须的更加困难。

这是其中一次运行的基本迭代(每小时每 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

相关内容