根据上一行更新行

根据上一行更新行

我有一个问题,因为我不熟悉 awk。我将 sar -d 输出生成的 csv 文件转换为 csv 样式:

12:33:41        unix,restarts
12:35:00,lofi4096,0,0.0,0,0,0.0,0.0
,iscsi0,0,0.0,0,0,0.0,0.0
,scsi_vhc,0,0.0,0,0,0.0,0.0
,nfs1,0,0.0,0,0,0.0,0.0

12:45:00,lofi4096,0,0.0,0,0,0.0,0.0
,iscsi0,0,0.0,0,0,0.0,0.0
,scsi_vhc,0,0.0,0,0,0.0,0.0
,nfs1,0,0.0,0,0,0.0,0.0

我想转换成这个

12:33:41        unix,restarts
12:35:00,lofi4096,0,0.0,0,0,0.0,0.0
12:35:00,iscsi0,0,0.0,0,0,0.0,0.0
12:35:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:35:00,nfs1,0,0.0,0,0,0.0,0.0

12:45:00,lofi4096,0,0.0,0,0,0.0,0.0
12:45:00,iscsi0,0,0.0,0,0,0.0,0.0
12:45:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:45:00,nfs1,0,0.0,0,0,0.0,0.0

我的尝试,但由于 awk 逐行读取,我不知道如何保留前一行的值。我希望我所拥有的应该有效。知道如何才能获得我想要的结果。我尝试使用 awk,但我想这应该可以使用 sed 或使用自定义 shell 脚本来实现(我试图避免执行这部分)。

#!/usr/bin/awk -f
BEGIN {
        FS=",";
}
{
        print $1
        if ($1 != "") {
                mydate=$1;
                print $0;
        }
        else {
                print $mydate","$0;
        }
}

运行Solaris 11.1系统。

答案1

由于输入中似乎有空行,因此它会有点长。以下内容可能对您有用:

awk -F'[, ]' '{if (NF!=0 && $1=="") {$1=prev} prev=$1}1' OFS=, inputfile

这个想法是分割字段,和空格(后者是为了处理第一行输入)。检查第一个字段是否为空字段数不为零(处理空行),然后用先前存储的第一个字段替换第一个字段。

对于您的输入,它会产生:

12:33:41        unix,restarts
12:35:00,lofi4096,0,0.0,0,0,0.0,0.0
12:35:00,iscsi0,0,0.0,0,0,0.0,0.0
12:35:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:35:00,nfs1,0,0.0,0,0,0.0,0.0

12:45:00,lofi4096,0,0.0,0,0,0.0,0.0
12:45:00,iscsi0,0,0.0,0,0,0.0,0.0
12:45:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:45:00,nfs1,0,0.0,0,0,0.0,0.0

答案2

sed

sed '/^[0-9]/{               # if line starts with digit
h                            # overwrite hold buffer with pattern space content
s/\([^,]*\),.*/\1/           # extract timestamp
x                            # exchange: put the original line back into pattern
}                            # space and the timestamp in hold space
/^,/{                        # if line starts with a comma
G                            # append hold space (timestamp) to pattern space
s/\(.*\)\n\(.*\)/\2\1/       # swap the initial line content and the timestamp 
}' infile

一行:

sed -e'/^[0-9]/{h;s/\([^,]*\),.*/\1/;x' -e\} -e'/^,/{G;s/\(.*\)\n\(.*\)/\2\1/' -e\} infile

答案3

其他sed

sed '$!N;/\n,/s/\([^,]*\).*\n/&\1/;P;D' <in >out

!对于不是最后一个的每个输入行$sed会将Next 输入行附加到模式空间,前面带有\newline 字符。然后,它将尝试进行s///替换,其中涉及将第一组可能的^,非逗号字符复制到紧跟在\newline 后面的逗号之前的空格。如果它不能这样做,我想也没有什么坏处。

sed然后将P打印到\n模式空间中的第一个 ewline 并D删除相同的内容,然后从顶部开始使用下一对输入行重新开始循环。

输出

12:33:41        unix,restarts
12:35:00,lofi4096,0,0.0,0,0,0.0,0.0
12:35:00,iscsi0,0,0.0,0,0,0.0,0.0
12:35:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:35:00,nfs1,0,0.0,0,0,0.0,0.0

12:45:00,lofi4096,0,0.0,0,0,0.0,0.0
12:45:00,iscsi0,0,0.0,0,0,0.0,0.0
12:45:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:45:00,nfs1,0,0.0,0,0,0.0,0.0

相关内容