invalid arithmetic operatior - bash

I am trying to multiply a integer value with a decimal value = 2*1.5. but how it gives me this error,"invalid arithmetic operator".
I researched online and most of the solution provided is just to add that | bc behind the decimal value but however I tried it and it still doesn't work,
results=$((2*"1.5"|bc))
echo $results

try this
results=`bc <<< "scale=2; 2*1.5"`
echo $results
here scale=2 means it will consider 2 decimal places
Please don't forget "`" tilde sign which is important above

You can also try the following:
echo "2*1.5" | bc

$a =2;
$a =(float)$a;
$b=1.5;
echo $a*$b;

Related

Updating (sequentially adding a value into) a variable within a for loop, in bash script

I am trying to update a variable within a for loop, sequentially adding to the variable, and then printing it to a series of file names.
Actually, I want to sequentially update a series of file, from a tmp file distTmp.RST to sequentially dist1.RST, dist2.RST, etc..
The original distTmp.RST contains a line called "WWW". I want to replace the string with values called 21.5 in dist1.RST, 22.5 in dist2.RST, 23.5 in dist3.RST, etc...
My code is as follows:
#!/bin/bash
wm=1
wM=70
wS=1
F=20.5
for W in {${wm}..${wM}..${wS}}; do
F=$(${F} + 1 | bc)
echo ${F}
sed "s/WWW/"${F}"/g" distTmp.RST > dist${W}.RST
done
echo ${F}
========
But I am getting error message as follows:
change.sh: line 13: 20.5 + 1 | bc: syntax error: invalid arithmetic operator (error token is ".5 + 1 | bc")
Kindly suggest me a solution to the same.
Kindly suggest me a solution to the same.
This might do what you wanted. Using a c-style for loop.
#!/usr/bin/env bash
wm=1
wM=70
wS=1
F=20.5
for ((w=wm;w<=wM;w+=wS)); do
f=$(bc <<< "$F + $w")
echo "$f"
sed "s/WWW/$f/g" distTmp.RST > "dist${w}.RST"
done
The error from your script might be because the order of expansion. brace expansion expansion happens before Variable does.
See Shell Expansion
Use
F=$(echo ${F} + 1 | bc)
instead of F=$((${F} + 1 | bc)). The doubled-up parentheses are what caused your error. Double parentheses weren't in the original code, but I get a different error saying 20.5: command not found with the original code, so I tried doubling the parentheses and get the error in the question. Apparently, floating point numbers aren't supported by $(()) arithmetic evaluation expressions in Bash.

Power of a power in bash with bc

I want to calculate this:
0x0404cb * 2**(8*(0x1b - 3))
which in decimal is:
263371*2^^(8*(27-3))
using | bc.
I tried with
echo 263371*2^^(8*(27-3)) | bc
expr 263371*2^^(8*(27-3)) | bc
zsh: no matches found: 263371*2^^(8*(27-3))
or try to resolve this
238348 * 2^176^
Can I resolve in one shot?
The bc "power of" operator is ^. You also have to quote everything to prevent the shell from trying to do things like history substitution and pathname expansion or interpreting parentheses as subhells:
$ bc <<< '263371*2^(8*(27-3))'
1653206561150525499452195696179626311675293455763937233695932416
If you want to process your initial expression from scratch, you can use the ibase special variable to set input to hexadecimal and do some extra processing:
eqn='0x0404cb * 2**(8*(0x1b - 3))'
# Replace "**" with "^"
eqn=${eqn//\*\*/^}
# Remove all "0x" prefixes
eqn=${eqn//0x}
# Set ibase to 16 and uppercase the equation
bc <<< "ibase = 16; ${eqn^^}"
or, instead of with parameter expansion, more compact and less legible with (GNU) sed:
sed 's/\*\*/^/g;s/0x//g;s/.*/\U&/;s/^/ibase = 16; /' <<< "$eqn" | bc

evaluate program output as an integer in bash

I have an application which outputs a string with a number, like this:
output number is 20.
I have a code which parses output and cutting out only the number:
result=$(./my_script | awk 'print $4')
echo $result
the result output will be "20" as expected, but now, if I would try to use it as an integer, for example:
result=$((result+1))
then I will get an error:
13915: syntax error: operand expected (error token is "20")
Using it as a seq argument will also give an error
$(seq 0 $result)
seq: invalid floating point argument: ‘\033[?25h\033[?0c20’
trying to print it with %q will give the same result:
printf '%q' $result
'\E[?25h\E[?0c20'
So, it looks like there are some unexpected characters in the string, but I'm not sure how to trim them?
Thank you!
You can try to get the number by using Regex.
It worked for me:
#!/bin/bash
result=$(bash output.sh | sed 's/[^0-9]//g')
r=$((result+1))
echo $r
Hope this helps.
Or, simply, change the field separator
result=$(./my_script | awk -F '[. ]' '{print $4}')
echo $result

Subtract 2 array values having floating point decimals

I'm reading a file with multiple columns, and dumping 2 columns of the file into into 2 different arrays. Now based on a condition, I need to get the difference between 2 values retrieved from the array. So my code looks like this -
if [ condition ]; then
VAL = (( ${local[$x]} - ${local[$y]} ))
fi
The thing is, while I'm able to echo and see both values ${local[$x]} and ${local[$y]}, the subtraction operation gives me a syntax error. I understand it's failing because the values currently held within the array involve floating point decimal values - like 3456712.126758, and the assignment throws errors with the decimal part. I understand arithmetic operations are not a strong point with the bash shell as floating point numbers are considered strings hence the issue.
Could you please help getting the right format please?
Should I do something like this
VAL= awk '{ print ${local[$x]} - ${local[$y]} }'
or
VAL=echo ${local[$x]} - ${local[$y]} | bc -l
I'm sure the syntax above is wrong, kindly help with the syntax, I need it assigned the subtracted result assigned to the field VAL.
Not only floating points, but also the spacing would lead to syntax errors. Bash variable assignments must have no spaces, as in val=x, and not val = x.
Uppercase variable names are reserved for environment variables, and it is recommended to use lowercase instead for your own variables. (Oh, and local is also a reserved word.)
Your assignment wouldn't work with proper spacing, either: the arithmetic expression
var=(( ${vals[$x]} - ${vals[$y]} )) # syntax error near unexpected token `('
is just evaluating its contents, but not returning anything. You could use the part after the = as a condition. To make it return something, you need arithmetic expansion (note the extra $):
var=$(( ${vals[$x]} - ${vals[$y]} )) # works for integers
^
In an arithmetic context, you don't even need to prepend $ to your variables:
var=$(( vals[x] - vals[y] ))
works just as well. Exception: in associative arrays, you still have to do it for indices:
$(( vals[$x] ))
And finally, as you noticed, this all doesn't work for floating point numbers. Instead of piping to bc, you can also use a here string and avoid spawning a subshell:
$ vals=(1.1 2.2)
$ x=0
$ y=1
$ echo $(( local[x] - local[y] )) # No '$' needed for variable expansion
bash: 1.1: syntax error: invalid arithmetic operator (error token is ".1") # But :(
$ bc -l <<< "local[x] - local[y]" # Requires '$' - these expand to nothing
0
$ bc -l <<< "${local[x]} - ${local[y]}" # Works!
-1.1
With awk:
awk -v a=${a} -v b=${b} 'BEGIN{print a - b}'
With bc:
echo "${a} - ${b}" | bc -l
See also other options here.

atoi() like function in bash?

Imagine that I use a state file to store a number, I read the number like this:
COUNT=$(< /tmp/state_file)
But since the file could be disrupted, $COUNT may not contain a "number", but any characters.
Other than using regex, i.e if [[ $COUNT ~ ^[0-9]+$ ]]; then blabla; fi, is there a "atoi" function that convert it to a number(0 if invalid)?
EDIT
Finally I decided to use something like this:
let a=$(($a+0))
Or
declare -i a; a="abcd123"; echo $a # got 0
Thanks to J20 for the hint.
You don't need an atoi equivalent, Bash variables are untyped. Trying to use variables set to random characters in arithmetic will just silently ignore them. eg
foo1=1
foo2=bar
let foo3=foo1+foo2
echo $foo3
Gives the result 1.
See this reference
echo $COUNT | bc should be able to cast a number, prone to error as per jurgemaister's comments...
echo ${COUNT/[a-Z]*} | bc which is similar to your regex method but not prone to error.
case "$c" in
[0-9])...
You should eat the input string charwise.

Resources