6

I have a issue since I'm not familiar with awk. I have csv file generated from sar -d output converted to csv style:

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

and I want to convert to this

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

My attempt but since awk reads line by line I don't know out to keep the previous line value. I would expect that what I have should work. Any idea how I can obtain my desired result. I tried with awk, but I guess this should be possible with sed or the hard way with a custom shell script ( I'm trying to avoid doing this part ).

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

Running the system with Solaris 11.1.

  • A lot of awk issues lately... – user123418 Jul 18 '15 at 1:35
3

It gets a bit long as you seem to have blank lines in the input. The following might work for you:

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

The idea is to split fields on , and whitespace (the latter in order to handle the first line of input). Check if the first field is blank and the number of fields is not zero (handle blank lines), then replace the first field with the previously stored first field.

For your input, it'd produce:

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
  • works like a charm, just in Solaris 11 it has to be the gawk ( it stands for gnu awk ). thanks a lot. – BitsOfNix Mar 29 '14 at 16:28
1

With 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

in one line:

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

Another sed:

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

For each input line which is ! not the $ last, sed will append the Next input line to pattern space as preceded by a \newline character. It will then attempt a s///ubstitution which involves copying the first possible group of ^, not-comma characters to the space just preceding a comma which immediately follows a \newline. If it cannot do so, well, no harm done, I guess.

sed will then Print up to the first \newline in pattern space and Delete same before beginning the cycle anew from the top with the next pair of input lines.

OUTPUT

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.