Bash in if check integer - bash

I have created a script in bash. I need to check if take 0 number then ignore this, but if take some value then I need to calculate based on the value given and print the result.
Here is an example:
if [ "$max_users_conn" -ne "0" ]; then
let "percentage="$process_list"*100/"$max_users_conn""
echo "$percentage"
fi
However, when I run the code, I receive the following error:
./mysql_conn.sh: line 14: [: 0 10: integer expression expected
./mysql_conn.sh: line 14: [: 0 10: integer expression expected
./mysql_conn.sh: line 14: [: 5 5: integer expression expected 0 20
I also tried to run it like this:
if [ "$max_users_conn" != "0" ]; then
let "percentage="$process_list"*100/"$max_users_conn""
echo "$percentage"
fi
But this gives a different error:
./mysql_conn.sh: line 15: let: percentage=4*100/0: division by 0
(error token is "0")
./mysql_conn.sh: line 15: let: percentage=4*100/0: division by 0
(error token is "0")
0 0 20

Bash does not allow you math expressions like other languages do, you need to use the $(( ... )) operator for this. However, this operator gives you only operations base on integers if you supply integers: echo $((2/4)) # => 0. If you do not care about fractions, though, it will help you. If you need fractions, utilize bc like anubhava showed in his answer.
Additionally, you should check that $max_users_conn actually contains a value.
So, rewrite your snipped to look like this:
if [ -n "$max_users_conn" -a "$max_users_conn" -ne 0 ]; then
percentage=$(( $process_list * 100 / $max_users_conn))
echo "$percentage"
fi
test "$a" -ne 0 checks for numeric values, while test "$a" != "$b" checks for string equivalence.

In BASH you can do:
if [[ $max_users_conn -ne 0 ]]; then
percentage=$((process_list * 100 / max_users_conn))
echo "$percentage"
fi
but keep in mind that BASH doesn't support floating point maths and you will get an integer value returned.
To get decimal number returned use this bc command above.
percentage=$(bc -l <<< "scale=2; $process_list * 100 / max_users_conn")

Related

Bash script error / integer expression expected [duplicate]

To satisfy function requirements I have to retrieve a parameter which is a duty cycle (0-100% in 0.01%).
For test, I wrote something simple like :
#!/bin/bash
#
if [ "$1" -lt 0 ] || [ "$1" -gt 100 ]
then
echo "bad param"
else
echo "ok"
fi
I obtain :
root#:~# ./test.sh 11
ok
root#:~# ./test.sh 11,01
./test.sh: line 4: [: 11,01: integer expression expected
./test.sh: line 4: [: 11,01: integer expression expected
bad param
How to realise this kind of test ?
bash can only operate in integer arithmetics. If you need floats, use an external tool like bc:
if (( $( bc <<< "($1 < 0) || ($1 > 100) " ) )) ; then
...
fi
I would rather switch to a more powerful language for the whole script, though (like Perl)/

If-statements in Bash Syntax issues produce right answers, while right code shows wrong answers [duplicate]

This question already has answers here:
Why should there be spaces around '[' and ']' in Bash?
(5 answers)
Closed 5 years ago.
I am fairly new to bash scripting and am struggling with some if-statement syntax.
I have currently written up the following loop:
for (( i = 2; i < $# - 1; i++)); do
if [ $i -ne 0]; then
if [ $i -ne 1]; then
echo "$i was not 1 or 0. Please correct this then try again."
exit 1;
fi
fi
done
This code is supposed to test whether any arguments after the first are either a 1 or a 0.
While the following errors are printed:
./blink.sh: line 36: [: missing `]'
./blink.sh: line 36: [: missing `]'
...the code actually runs fine afterwards (so the errors don't kill the program).
My understanding, however, is that in bash, you put spaces before and after the expression inside the if statement. So this:
if [ $i -ne 0]; then
Becomes:
if [ $i -ne 0 ]; then
However, running this code produces the following:
2 was not 1 or 0. Please correct this then try again.
The main issue I am having with this stems from not understanding how to indirectly reference the positional arguments provided by the execution command. As such, I am confused as to what syntax must be altered to call the objects the arguments point to (in this case, hopefully either a 1 or a 0) rather than the position of the arguments themselves (argument 1, 2, 3...).
Thanks!
EDIT: Altering the question to better fit the advice #randomir provided and clear up what the actual question entails
Based on:
This code is supposed to test whether any arguments after the first are either a 1 or a 0.
I'm assuming you're trying to access positional arguments $2, $3, etc. To make your for loop solution work, you would have to use an indirect reference: ${!i} (see shell parameter expansion). For example, this should work:
#!/bin/bash
for (( i = 2; i <= $#; i++ )); do
if [[ ${!i} -ne 0 ]]; then
if [[ ${!i} -ne 1 ]]; then
echo "$i was not 1 or 0. Please correct this then try again."
exit 1;
fi
fi
done
Note the i running from 2 to number of arguments $#. Also, note the use of recommended and less error-prone [[ .. ]] instead of [ .. ] (otherwise you would have to write [ "${!i}" -ne 0 ], etc).
A simpler solution which avoids the unnecessary indirect referencing looks like this:
#!/bin/bash
while [[ $2 ]]; do
if (( $2 != 0 && $2 != 1 )); then
echo "$2 is neither 0, nor 1"
exit 1
fi
shift
done
We start checking the second argument ($2), use the arithmetic expression (( expr )) testing of value of the second argument, and shift positional arguments to the left by 1 at each iteration (now $3 becomes $2, etc).

bash handle both starts with non-zero and zero value in if

I need to compare two integer values and here is the if condition,
if [[ $VAL -ge 1000 ]] ; then
#do something
fi
But the problem is when it tries to compare with an integer value 010 got the error saying
-bash: 01: value too great for base (error token is "01")
I fixed this issue by using $VAL#0 in if condition.
But still getting same kind of issue with it tries to compare integer value 0010 and it fixed with 10#${VAL}.
The problem with proper integer values like 523 and getting below error,
[[: #10523: syntax error: operand expected (error token is "#10523")
Not sure how to make the if statement works with all the cases.
Update (Solution):
Found the fix.
VAL=$((10#$VAL))
Whatever value this will change it to decimal and reassign it to the same variable.
I think there's something not quite right with your example. 010 will not give a base error, but e.g. 090 will. That's because numbers with a leading zero are assumed to be octal.
To manually set the base, prefix the number with 10#:
$ if [[ 100 -gt 090 ]]; then echo t; else echo f; fi
bash: [[: 090: value too great for base (error token is "090")
f
$ if [[ 100 -gt 10#090 ]]; then echo t; else echo f; fi
t
For your case, that means you should use:
if [[ "10#$VAL" -ge 1000 ]] ; then
#do something
fi

convert read string to integer in bash

I'm trying to read from user and then do the following.
read framechoice
if [ $framechoice -gt 100 ]; then
if [ $framechoice -lt 0 ]; then
framechoice=101
fi
fi
It gives me the following error.
[: -gt: unary operator expected
Can anyone tell me where I am going wrong.
This happens if you don't input anything:
$ cat myscript
read framechoice
if [ $framechoice -gt 100 ]; then
if [ $framechoice -lt 0 ]; then
framechoice=101
fi
fi
$ bash myscript
<enter>
myscript: line 2: [: -gt: unary operator expected
Try instead to actually enter something:
$ bash myscript
42<enter>
The script then exits with success.
Your program needs to cope with empty input. This is most easily achieved by properly quoting the variable; then
if [ "$framechoice" -gt 100 ]; then
evaluates to [ "" -gt 100 ] which is no longer is a syntax error; however, instead, it throws the warning integer expression expected.
Even better, maybe filter the input so that you do not attempt numeric comparisons before making sure the input is numeric.

filtering files by number in bash error unary operator expected

I have a script that will find the distances between two atoms in pdb.
bash does not recognize decimals so I have put printf script to round the decimals.
and echo $b works fine and gives me a integer value.
but the if line for my filtering system does not work.
I get and error stating
[: -ge: unary operator expected
below is part of the script that I am working on.
a=$(awk '$2=='91'{x1=$6;y1=$7;z1=$8} $2=='180' {x2=$6;y2=$7;z2=$8} END{print sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2))}' ${names}.pdb.$i)
b= printf %.0f $a
echo $b
if [ $b -ge 1 ] &&[ $b -le 9 ]; then
any help will be greatly appreciated. Thank you in advanced.
b= printf %.0f $a
This line sets the value of b to nothing for the duration of the printf command, which sends its output to stdout
echo $b
This prints a blank line.
You must not put whitespace around the = in an assignment, and to store the output of a command into a variable, you use this syntax:
b=$( printf %.0f $a )
You're getting the error because $b is empty, and this is what bash sees:
if [ -ge 1 ] &&[ -le 9 ]; then
-ge is expecting operands on both the left and the right, and it doesn't see one.
With bash, you should (almost) always prefer [[ ... ]] over [ ... ] -- the double bracket form is not fooled by variables containing empty strings.
You should always quote your "$variables" -- unless you know exactly when to not quote them.

Resources