Anup
Anup

Reputation: 91

Total value in file using shell script where values in gb,mb,kb,b

I have a file where values in a column with unit mb,kb,b and gb, I want total of these value using shell script and output will come in Total gb

cat test_file

24k
556m
1.2g
6.2m
17m
24k
254b
30g
1.6g
28k
120b

I'm able to convert byte data into mb but stuck to convert kb and sum total of all

test=0 
for i in `cat test_file` 
do 
b=echo $i|tr -d '[:alpha:]' 
a=echo $i|tr -d '/0-9,\./' 
if [ "$a" == "b" ]; then 
b=($b/1024) fi test=echo $test + $b | bc 
done 
result=$(echo "scale=2; $test / 1024" | bc) 
echo $result 

Upvotes: 2

Views: 1315

Answers (2)

mivk
mivk

Reputation: 14889

Here is a Perl version:

perl -nle 'BEGIN {for (qw(k m g t)) {$m{$_}=1000**++$i}}; ($v,$u)=/([\d\.]+)([kmgt])?/; $v*=$m{$u} if $u; $t+=$v; END {print "Total $t Bytes\n"}' test_file 

Or on multiple lines for readability:

perl -nle '
  BEGIN { for (qw(k m g t)) {$m{$_}=1000**++$i} }; # create multipliers hash
  ($v,$u) = /([\d\.]+)([kmgt])?/;                  # get value and optional unit
  $v *= $m{$u} if $u;                              # multiply to get bytes (if unit was specified)
  $t += $v;
  END { print "Total $t Bytes\n"}' test_file 

This gives megabytes as 1'000'000 bytes. If your values represent binary Mebibytes etc., replace 1000 by 1024.

A more readable version of the initialization of the multiplier hash would be:

BEGIN { @m{ qw(k m g t) } = (1000, 1000**2, 1000**3, 1000**4) };

If your units may also be written in mixed case, add $_=lc; before the regex to first make it all lowercase.

Upvotes: 0

RavinderSingh13
RavinderSingh13

Reputation: 133538

1st solution: Using switch case in GNU awk:

awk '
{
last_char=tolower(substr($0,length($0)))
switch(last_char){
  case "k":
    sum+=($0+0)/(1024*1024)
    break
  case "m":
    sum+=($0+0)/(1024)
    break
  case "g":
    sum+=$0+0
    break
  case "b":
    sum+=($0+0)/(1024*1024*1024)
    break
  case "?":
    print "Line is not matching anything here...."
}
}
END{
  print sum
}'  Input_file


2nd solution: Could you please try following, this solution is using if, else conditions.

awk '
{
  if($0~/[kK]$/){
    sum+=($0+0)/(1024*1024)
  }
  if($0~/[mM]$/){
    sum+=($0+0)/(1024)
  }
  if($0~/[gG]$/){
    sum+=$0+0
  }
  if($0~/bB]$/){
    sum+=($0+0)/(1024*1024*1024)
  }
}
END{
  print sum
}
'  Input_file

Upvotes: 3

Related Questions