Q:

(standard_in) 1: parse error

I'm writing a quick script for calculating individual interface throughput from data pulled from /proc/net/dev and I'm having an issue. It converts it from bytes to megabits.
This is working on my ubuntu server (3.2.0 kernel), however when I try and run this on older devices (2.6.18 era) it's not working. I'm not sure what I'm doing wrong.
Here's a snippet of my code:
int1_byte_rx=`cat $logfile | grep $int1 | awk '{print $2}' | awk '{sum+=$1} END {print sum}'`
int1_byte_tx=`cat $logfile | grep $int1 | awk '{print $10}' | awk '{sum+=$1} END {print sum}'`
int1_rx_thrpt=$(echo "($int1_byte_rx * 0.00000762939453) / $iterations / ($time * 60)" | bc -l)
int1_tx_thrpt=$(echo "($int1_byte_tx * 0.00000762939453) / $iterations / ($time * 60)" | bc -l)

When I run this I get the following error (from debug mode):
int1_rx_thrpt=$(echo "($int1_byte_rx * 0.00000762939453) / $iterations / ($time * 60)" | bc -l)
echo "($int1_byte_rx * 0.00000762939453) / $iterations / ($time * 60)" | bc -l
++ echo '(1.13417e+10 * 0.00000762939453) / 57 / (5 * 60)'
++ bc -l
(standard_in) 1: parse error
(standard_in) 1: parse error
+ int1_rx_thrpt=
int1_tx_thrpt=$(echo "($int1_byte_tx * 0.00000762939453) / $iterations / ($time * 60)" | bc -l)
echo "($int1_byte_tx * 0.00000762939453) / $iterations / ($time * 60)" | bc -l
++ echo '(9.78048e+09 * 0.00000762939453) / 57 / (5 * 60)'
++ bc -l
(standard_in) 1: parse error
(standard_in) 1: parse error

I've been able to trace the problem back to bc itself, however I'm not actually sure how to correct it.
Any advice is welcome.
Thanks for your time,

A:

You don't need those long pipelines and you don't need to use bc.
int1_byte_rx=$(awk -v int="$int1" '$0 ~ int {sum += $2} END {print sum}' "$logfile")
int1_byte_tx=$(awk -v int="$int1" '$0 ~ int {sum += $10} END {print sum}' "$logfile")
int1_rx_thrpt=$(awk -v int1_byte_rx="$int1_byte_rx" -v iter="$iterations" -v time="$time" 'BEGIN {printf "%12.2f", (int1_byte_rx * 0.00000762939453) / iter / (time * 60)}')
int1_tx_thrpt=$(awk -v int1_byte_tx="$int1_byte_tx" -v iter="$iterations" -v time="$time" 'BEGIN {printf "%12.2f", (int1_byte_tx * 0.00000762939453) / iter / (time * 60)}')

You can combine the first two lines like this:
read -r int1_byte_rx int1_byte_tx <<< $(awk -v int="$int1" '$0 ~ int {sumrx += $2; sumtx+= $10} END {print sumrx, sumtx}' "$logfile")

and you'll only have to read the logfile once.
Another alternative would be to write the entire script in AWK or another language that supports floating point arithmetic such as Python or Perl.

A:

My /proc/net/dev doesn't have large enough values to force awk to print any output in scientific notation, so I cannot easily test this, but here's my suggested fix:
int1_byte_rx=`cat $logfile | grep $int1 | awk '{print $2}' | awk '{sum+=$1} END {printf "%f", sum}'`
int1_byte_tx=`cat $logfile | grep $int1 | awk '{print $10}' | awk '{sum+=$1} END {printf "%f", sum}'`

(Note the printf "%f", portion near the end.)
The trick is to prevent awk from generating the scientific format in the first place.

