syntax error: operand expected (error token is "+ ") in bash - bash

I am trying to calculate the sum of numbers entered via command line to my script file. Here is my code
#!/bin/bash
for ((i=0;i<=$#;i++))
do
sum=$(($i + $sum))
done
echo $sum | bc
My terminal input is
bash file.sh 1 2
So the output should be 3 but I am getting
syntax error: operand expected (error token is "+ ")

The actual error reason is because of uninitialized variable sum going through the first iteration of the loop. Initialize the variable before entering the loop.
Also a major logical flaw is that you are not even iterating over the input arguments, but just over the counter i which will produce incorrect results if you pass arguments other than 1 2 from the command-line.
You need to pass over the actual arguments argc and argv (arg count and arg vector: for understanding purposes only) and you don't need bc at all
argc=$#
argv=("$#")
sum=0
for ((i=0; i<${argc}; i++)); do
sum=$((${argv[i]} + $sum))
done

To loop over all command line arguments, you can use the simplified form of the shell for statement:
sum=0
for i do
((sum += i))
done
((sum+=i)) is accepted by bash and many other shells; for a Posix-compatible shell, you can use arithmetic expansion with the : builtin:
: $((sum += i))

Related

Bash arithmetic expansion with for loop

I am trying to write a loop that uses command line arguments to determine the range over which it operates. As of now I've tried the following:
let a=$1
let best=$2
for ((i=a ; i < best ; i++)); do
let bwd_g = $((20 - i))
echo $bwd_g
done
when I call ./test.sh the following output is produced:
./test.sh: line 9: let: =: syntax error: operand expected (error token is "=")
I've spent a large amount of time on coming up with different variants of this code but to no avail and have tried googling the error message.
Though I am not fully sure about your requirement, but to fix your specific error, try wrapping let with " and it should fly then, like (there shouldn't be any spaces between variable name(s) and =):
cat script.sh
let a=$1
let best=$2
for ((i=a ; i < best ; i++)); do
let "bwd_g = $((20 - i))"
echo $bwd_g
done
You should use $((.....)) for doing operations in bash, so better use following rather than let:
cat script.sh
a=$1
best=$2
for ((i=a ; i < best ; i++)); do
bwd_g=$((20 - i))
echo $bwd_g
done
I think the issue was with blank spaces on line 4. Please check below.
let a=$1
let best=$2
for ((i=a ; i < best ; i++)); do
let bwd_g=$((20 - i))
echo $bwd_g
done
and I ran it as
bash script.sh 5 10

How to turn a function output, into a number [duplicate]

This question already has answers here:
How can I compare two floating point numbers in Bash?
(22 answers)
Floating point comparison in shell
(7 answers)
Closed 4 years ago.
So want to turn this function, whose output is a number. The number is curled through some json file thats irrelevant.
#error input 1
if (($(masterfunc) >= 1)); then
#I've also tried
#error input 2
if (($(masterfunc | bc -l) >= 1)); then
I get these this error, which I'm assuming is because its outputing it as a letter or command and not as a number.
#error output 1
((: 1.00048333447157914468 >= 1: syntax error: invalid arithmetic
operator (error token is ".00048333447157914468 >= 1")
#error output 2
((: .99989817794934530799 >= 1: syntax error: operand expected (error
token is ".99989817794934530799 >= 1")
I'm assuming this is some floating point arithmetic problem, but then it should of been solved through bc?
I'm new to bash so if the problem is some unrelated syntax error I apologize.
This is actually rather complicated. The shell doesn't understand real numbers at all, so you have to get something else (like bc) to do the comparison and output something simpler that bash can understand. The simplest way I see to do this is:
if [ $(echo "$(masterfunc) >= 1" | bc) -eq 1 ]; then
Explanation, step by step:
echo "$(masterfunc) >= 1" runs the masterfunc function, adds ">= 1" to its output, and sends the result (something like "1.00048333447157914468 >= 1") to standard output.
echo "$(masterfunc) >= 1" | bc runs the above and pipes it to bc, which will do the comparison and print "1" if the masterfunc output is greater than or equal to 1, "0" if it's less. Note: you can try running this by hand and see how it works.
This "1"/"0" output is more along the lines of what bash can understand, but we still need to actually tell bash what to make of it.
[ $(echo "$(masterfunc) >= 1" | bc) -eq 1 ] runs the above, captures its output with $( ), and embeds that in a test expression. Basically, depending on the output from bc, this is equivalent to either [ 1 -eq 1 ] or [ 0 -eq 1 ].
Use this:
if (( $(printf '%s >= 1\n' "$(masterfunc)" | bc -l) )); then ...

expr displaying the expression rather than solving it

Here is my shell script,
#! /bin/sh
# basic calculator
echo "Please input your choice"
printf " 1.Addition \n 2.SUbstraction \n 3.Multiplication \n 4.Division\n"
read choice
case "$choice" in
1) echo "Enter number 1:";read n1;echo "Enter number 2:";read n2;t=$(expr "$n1"+"$n2");echo "$n1+$n2=$t";;
2) echo "Enter number 1:";read n1;echo "Enter number 2:";read n2;t='expr $n1-$n2';echo "$n1-$n2=$t";;
3) echo "Enter number 1:";read n1;echo "Enter number 2:";read n2;t='expr $n1\*$n2';echo "$n1*$n2=$t";;
4) echo "Enter number 1:";read n1;echo "Enter number 2:";read n2;t='expr $n1/$n2';echo "$n1/$n2=$t";;
esac
Here is my output,
Script started on Sunday 08 November 2015 12:05:21 PM IST
Please input your choice
1.Addition
2.SUbstraction
3.Multiplication
4.Division
1
Enter number 1:
5
Enter number 2:
6
5+6=5+6
The problem is that my expr isnt actually solving the expressions
Whitespace matters:
$ expr 5+6
5+6
$ expr 5 + 6
11
To do arithmetic, you need to give expr 3 distinct arguments.
In some versions of expr it's recommended to use shell arithmetic instead:
$ echo $((5+6))
11
$ echo $((5>=6))
0
Using shell arithmetic using spaces to separate ints is not necessary if desired.
The expr utility makes no lexical distinction between arguments which
may
be operators and arguments which may be operands. An operand which is
lexically identical to an operator will be considered a syntax error.
The syntax of the expr command in general is historic and inconvenient.
New applications are advised to use shell arithmetic rather than expr
You are using single quotes (') instead of backticks ( ` ) for the other calls to expr. But as I'L'l points out, there's almost never any reason to use expr to perform arithmetic.

confirm numeric character of variable

I need to do an operation but something is wrong in my code in bash
I have 4 variables, km1, km2, km3, km4.
I want to sum the 4 variables except when the value is "CLOSED"
3.200
CLOSED
1.800
0.600
When I do the following sum, there is an error...I thing my variables are not numeric, any help? How can I force them to be numeric and then do the sum?
let km=$km1+$km3+$km4
echo $km
./sum.sh: line 41: let: km=3.200: syntax error: invalid arithmetic operator (error token is ".200")
km1=3.200
km2=CLOSED
km3=1.800
km4=0.600
total=`LC_ALL=C echo "$km1 $km2 $km3 $km4"|awk '{sum += $1+$2+$3+$4}END {print sum}'`
Not that good with awk but i think the above can help. total the is sum of all vars
There are 2 issues with you code. The first one is that you are trying to work with values other than integers. Bash only does integers. You can round up the values to integers using bc (An arbitrary precision calculator language). The second issue is that you are trying to do math on strings. So consider the code below:
#!/bin/bash
km1=3.200;
km2="CLOSED";
km3=1.800;
km4=0.600;
km1=$(echo "$km1/1" | bc)
km3=$(echo "$km3/1" | bc)
km4=$(echo "$km4/1" | bc)
array=($km1 $km2 $km3 $km4)
for i in ${array[#]}; do
case $i in
*[0-9]*)
(( result+=$i ))
esac
done
echo $result

How to assign array length to a variable in bash

I'm trying to write a simple bash script that adds integers and supplies the sum. I figured the easiest way would be to assign the input to an array. Then traverse the array to perform the summation. I need to use the length of the array in my for loop and cannot figure out how to assign the array length to a variable.
Any help appreciated on the simple script (which I did to learn bash)
#!/bin/bash
# add1 : adding user supplied ints
echo -n "Please enter any number of integers: "
read -a input
echo "Your input is ${input[*]}"
echo "${#input[#]} number of elements"
num = ${#input[#]} # causing error
for ((i = 0; i < "${num}"; ++i )); do # causing error
sum = $((sum + input[$i]))
done
echo "The sum of your input is $sum"
Which yields the errors:
line 10: num: command not found
line 11: ((: i < :syntax error: operand expected (error token is "< ")
You just have a syntax error. Remove the space before =:
num = ${#input[#]} # causing error
becomes:
num=${#input[#]} # works
Note that if you assign to a variable in bash using the = operator, there MUST NOT be any space before and after the =
Read this entry about Variable Assignment in the Advanced Bash-Scripting Guide

Resources