0

I'm trying to extract the sum of numbers to a variable (cwr) in a file (wa_cidr) using this command:

cwr=$(grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$" /tmp/wa_cidr | awk -F '/' '`{n += 2**(32 - $NF)}` END {print n}')

However, the output is empty.

If I change the part...

{n += 2**(32 - $NF)} 

To...

{n += (32 - $NF)} 

I get a valid result written to the cwr variable.

It would seem that I cannot do the power of (32 - $NF) using either 2**X or 2^X in AWK.

If I do it on the command line, e.g. using...

$ echo $(2**5)

There's no problem and the result is 32.

I have tried many variations on the formula (parantheses etc.) but nothing seems to Work.

What is wrong? Can it be done in another way?

Thanks, Søren

a15995
  • 17
  • 5
  • Please show us a sample input line that produces the symptom you describe. – mklement0 Oct 29 '16 at 16:04
  • Also, I assume you meant `awk 'BEGIN { print 2**5 }'` as an interactive test (in the _shell_, you'd have to do `echo $((2**5))` (`$((...))` for arithmetic expansions), but that's not relevant here, given that your problem is with an _Awk_ script). – mklement0 Oct 29 '16 at 16:24
  • I'd be interested to know why you're doing "power of" on a DD-WRT box ? Thanks for sharing (if you can). Solution below is most certainly correct. Good luck. – shellter Oct 29 '16 at 23:35
  • @shellter - see below and here: http://www.dd-wrt.com/phpBB2/viewtopic.php?p=1051848 – a15995 Oct 30 '16 at 08:54
  • @mklement0 - this line ´grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$" /tmp/wa_cidr | awk -F '/' '{n += (32 - $NF)} END {print n}'` gives the output '524', but this line `grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$" /tmp/wa_cidr | awk -F '/' '{n += 2^(32 - $NF)} END {print n}'` gives an empty output. Even if 32 - $NF is zero (cannot be negative) the result would be 1. Maybe I need a command parameter to activate "advanced" calculations or something? – a15995 Oct 30 '16 at 09:01
  • By the way - doing the exact same calculation in Excel gives the output 524 before power of and 3996 after - sum of `(32-$NF)` = 524 / sum of `2^(32-$NF)` = 3996... – a15995 Oct 30 '16 at 09:17
  • Doe a _single_ calculation fail? Please add any clarifications - and, ideally, sample input that demonstrates the problem _directly to your answer_. – mklement0 Oct 30 '16 at 13:35

2 Answers2

1

If your regexp is correct then this would be the correct syntax to do what you appear to be trying to do:

cwr=$(awk -F'/' '/^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$/{n += 2^(32 - $NF)} END {print n+0}' /tmp/wa_cidr)
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • Hmm that do seems like the way to go, but I get this error: `Stopped (tty input)` I think there may be some limitations in the DD-WRT shell but I'm at a loss as to why a simple calculation would cause problems. To clarify: I'm trying to extract CIDR's from the file wa_cidr, get the number after the slash (e.g. IP/30), calculate numbers of IP's in that segment and return the result to $cwr. Thís works with my command - except - I cannot do the proper calculation (power of) with that number. I do see your code is better but now I get this error...? Thanks, Søren – a15995 Oct 30 '16 at 08:52
  • 1
    It was a typo, I'd put the file name after the last `)` instead of before it. Fixed now. That's one reason it's in your best interests to always provide testable sample input/output when you post a question (i.e. a [mcve]) because without it we can't test a potential solution before posting it. – Ed Morton Oct 30 '16 at 15:26
1

Hmmm, it would appear that I was on to something, when I mentioned that something was limited in the DD-WRT Shell.

According to this website, https://rosettacode.org/wiki/Exponentiation_operator#awk, the "traditional awk implementations do not provide an exponent operator, so we define a function to calculate the exponent".

So for the code to Work it needs to look something like this:

cwr=$(grep -E "^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$" /tmp/wa_cidr | awk -F '/' 'function pow(x,n){r=1;for(i=0;i<n;i++)r=r*x;return r}{c += pow(2,(32-$NF))} END {print c}')

Which gives the correct value of 3996.

Thank you all for inputs!

/Søren

a15995
  • 17
  • 5