hi,

i am totally stuck i need a script (that works in ksh under solaris 10) that takes the following output

d15 509MB c1t0d0s5
d13 7.0GB c1t0d0s3
d11 1.5GB c1t0d0s1
d10 10GB c1t0d0s0
d25 509MB c1t1d0s5
d23 7.0GB c1t1d0s3
d21 1.5GB c1t1d0s1
d20 10GB c1t1d0s0

and for the second column turn all values into MB and removes the MB and GB text. Some are already shown in mb and some are in GB. I think using awk would be the easiest but awk is not my strong point. The command i use to get the output in the first place is :

metastat -c | grep "s" | grep $DISK  | awk '{print $1,$3,$4}'\
         > ${UFSDISKSLICE}_${DISK}_${Date}

any help??

One of the biggest problems here, is getting the shell to handle floating point numbers. I'm not using / have access to a solaris machine, so I'm going strictly of bash in slackware.... but the shell doesn't handle floating point numbers. In a Perl script, I could knock this out, or in a C++ program, it would be a breeze... but doing this as a shell script, is an entirely different beast. Parsing the data with awk or sed would be alright, but converting the numbers is an entirely different challenge. In perl, it is pretty easy:

#!/usr/bin/perl

push @lines, "d15 509MB c1t0d0s5";
push @lines, "d13 7.0GB c1t0d0s3";
push @lines, "d11 1.5GB c1t0d0s1";
push @lines, "d10 10GB c1t0d0s0";
push @lines, "d25 509MB c1t1d0s5";
push @lines, "d23 7.0GB c1t1d0s3";
push @lines, "d21 1.5GB c1t1d0s1";
push @lines, "d20 10GB c1t1d0s0";

foreach $line (@lines) {
	($dcode, $unit, $drive) = split(/\s/, $line);

	if (substr($unit, (length($unit) -2), 2) eq "GB") {
		$unit = substr($unit, 0, length($unit) -2);
		$unit = ($unit * 1024); 		# // Convert To MB
	} else {
		$unit = substr($unit, 0, (length($unit) -2));
	}

	print "$dcode\t$unit\t$drive\n";
}

Assuming data format:

d15 509MB c1t0d0s5
d13 7.0GB c1t0d0s3
d11 1.5GB c1t0d0s1
d10 10GB c1t0d0s0
d25 509MB c1t1d0s5
d23 7.0GB c1t1d0s3
d21 1.5GB c1t1d0s1
d20 10GB c1t1d0s0

For example purposes coming from datafile to awk and displaying to standard output. Modify to need.

awk '/s/ {
        if ( index($2, "GB") ) {
            $2 = sprintf("%10.2f", ($2*1024))
        }
        else {
            $2 = sprintf("%10.2f", $2)
        }
        print $0 
}' datafile

No need of calling grep to pipe only lines containing an s at column $3

/* output example
d15     509.00 c1t0d0s5
d13    7168.00 c1t0d0s3
d11    1536.00 c1t0d0s1
d10   10240.00 c1t0d0s0
d25     509.00 c1t1d0s5
d23    7168.00 c1t1d0s3
d21    1536.00 c1t1d0s1
d20   10240.00 c1t1d0s0
*/
Comments
Genius! Well Done.

Hi,

I get the following output:

d15       0.00 c1t0d0s5
d13       0.00 c1t0d0s3
d11       0.00 c1t0d0s1
d10       0.00 c1t0d0s0
d25       0.00 c1t1d0s5
d23       0.00 c1t1d0s3
d21       0.00 c1t1d0s1
d20       0.00 c1t1d0s0

Im using solaris 10 and the script is running with KSH could this be causing it?

Hi,
Im using solaris 10 and the script is running with KSH could this be causing it?

You get that result because sprintf is not receiving any value in column $2 that can convert into a decimal.
For debugging purposes substitute every line with a sprintf() call for just a print of $2 to see the result.

You could also post your script and help us to help you.

Hi,

To test it I was simply placing the data into a file in /tmp/datafile then the scripts looks like the following its also run from temp

#!/bin/ksh
awk '/s/ {
        if ( index($2, "GB") ) {
            $2 = sprintf("%10.2f", ($2*1024))
        }
        else {
            $2 = sprintf("%10.2f", $2)
        }
        print $0 
}' datafile

If I take out the sprintf line and just use print $2 at end of the script I get the following:

509MB
7.0GB
1.5GB
10GB
509MB
7.0GB
1.5GB
10GB

So sprint if getting the values however they still have either MB or GB on the end so therefore the sprintf statement wouldnt work would it?

>So sprint if getting the values however they still have either MB or GB on the end so therefore the sprintf statement wouldnt work would it?

Yes, it would. sprintf() tries to read and convert any string to the format you give it.
To convince you run

echo "1.2GB" | awk '{print sprintf("$8.2f", $1)}'

...and watch the result.

hi,

Just tried that from the command line and I still get 0.00! any ideas what could be doing it?

Hey Chris,

It looks like just a simple typo in Aia's reply. Just change $8.2f to %8.2f and you should get "1.20"

, Mike

hi,

I did notice the typo but even with it changed to % it still doesnt work the exact command im trying is :

root@testbench2:/tmp #echo "1.2GB" | awk '{print sprintf("%8.2f",$1)}'
    0.00

but if i take of the GB then it works:

echo "1.2" | awk '{print sprintf("%8.2f", $1)}'
    1.20

any ideas?

>any ideas?
I am not running any version of Solaris so I don't know what's the "gotcha."
But if sprintf() is doing the job after the suffix "GB" is erased, let's do it.
Make an awk file that contains this:

#!/usr/bin/awk -f

$3 ~ /s/ {
    if ( index($2, "GB") ) {
        split($2, dissect, "G");
        $2 = sprintf("%8.2f", (dissect[1]*1024));
    }
    else {
        split($2, dissect, "M");
        $2 = sprintf("%8.2f", dissect[1]);
    }
    print $0
}

Then, call it with the input file

awk -f convert.awk data > outputdata

Where convert.awk is this awk file we talked about previously, data is the output to analyzed, and outputdata is the result file.
Note: check that awk lives in the /usr/bin/awk. If not, change in awk file accordingly. Usually the command which awk will tell you.

This question has already been answered. Start a new discussion instead.