2

I have file which has log size like,

10.80 kb
60.08 kb
35.40 kb 
2.20 MB
1.10 MB
40.80 kb
3.15 MB
20.50 kb

I want to add awk one liner in such a way that it satisfy below conditions,

  1. Convert kb to MB (divide by 1000)
  2. get total in MB

I have written below awk code but it fails to add MB,

awk '{FS=" "} if ($2 ~ 'kb'){total += ($1/1000)}END{print total}'

This will convert kb's into MB and provide total but it does not add MB values to it. Please suggest?

John1024
  • 109,961
  • 14
  • 137
  • 171
Rock
  • 157
  • 1
  • 3
  • 13

3 Answers3

4

Try:

$ awk '{if ($2=="kb") total+=$1/1000; else total+=$1} END{print total}' file
6.61758

How it works

For each line, the if statement is executed:

if ($2=="kb") total+=$1/1000; else total+=$1

If the second field is kb, then the total is increased by the first field divided by 1,000. Otherwise, it is is increased by the first field.

After the code has finished reading the file, the total is printed.

Multi-line version

For those who prefer their code spread over multiple lines:

awk '
    {
        if ($2=="kb") 
           total+=$1/1000
        else
           total+=$1
     }

     END{
         print total
     }' file
John1024
  • 109,961
  • 14
  • 137
  • 171
4

Using ternary operator:

$ awk '{total+= $1 / ($2=="kb" ? 1000: 1)}END{print total}' file
6.61758

Explanation

The operator syntax:

expr ? action1 : action2

In this example:

$2=="kb" ? 1000: 1

Depending of second field value (expr), our program will perform a different action, in this case its returning the numerical value of 1000 (action1) or just 1 (action2).

At this point total variable is used for accumulate $1 value divided by the result given by the ternary operator.

total+= $1 / ($2=="kb" ? 1000: 1)

Check this.

Juan Diego Godoy Robles
  • 14,447
  • 2
  • 38
  • 52
  • How does this work. Can you please elaborate, {total+= $2=="kb" ? $1/1000: $1} – Rock Sep 12 '16 at 18:40
  • For catching the `'kb'` issue: +1. – John1024 Sep 12 '16 at 18:47
  • 1
    @Rock, google ternary operator to find the likes of `https://en.wikipedia.org/wiki/%3F:`. I couldn't use a hyperlink as the SO editor cuts off the ending `:`! Note that an unpaerentheiszed ternary expression will cause syntax errors in some awks in some situations. I'd use `total+= ($2=="kb" ? $1/1000: $1)` or even better `total+= $1 / ($2=="kb" ? 1000: 1)` instead. – Ed Morton Sep 12 '16 at 19:54
1

"kb" (really kB) to MB conversion is kB divided by 1024. In the following kb and kB assumed as kB:

$ awk '$2 ~ /k[bB]/ {$1/=1024} {sum+=$1} END {print "sum:" sum}' foo
sum:6.61365
James Brown
  • 36,089
  • 7
  • 43
  • 59
  • 1
    That should be true. It was true until the marketing people (who think larger numbers make for an easier sale) became involved. Now, `kiB = 1024 B` and `kB = 1000 B`. As @ghoti pointed out, this is documented [here](https://en.wikipedia.org/wiki/Mebibyte). – John1024 Sep 12 '16 at 21:58
  • Well, long live SI. It's heaven and hell. So have i typeth on min typewriterth. – James Brown Sep 12 '16 at 22:08
  • 1
    For standing up for honesty and tradition: +1. – John1024 Sep 12 '16 at 22:10