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)/
Related
what is the correct syntax to decrement/decrease the variable value by 1 in while loop using /bin/sh and not using /bin/bash script
I used following but does not work
a=15
((a=a-1)) // not working
((a--)) // not working
EDIT 1
i=0
a=[]
b=15
while [ $a == [] ] && [ "$i" -le 15 ]
do
echo " Waiting ."
sleep 60s
((i=i+1))
b=`expr $b- 1`
a=`some command`
done
still getting following error
sh: was: unknown operand /bin/sh: exit: line 186: Illegal number: -1
Arithmetic substitution is spelled $(( )) and expands to the result. If you just need the side effect (e.g. increment), use it in a null command:
a=15
: $((--a))
echo $a
Note that shell arithmetic is integer only.
$ a=15
$ a=`expr $a - 1`
$ echo $a
14
Below is code which I developed. I am passing four arguments in function and want to return variable output which I am passing to that function as a argument number four. I am getting below mentioned error.
test.sh
output='PASS'
A=(1.0,1.0,1.0,1.0,0.0,1.0)
T=(1,2,3,4,5,6)
function compare(){
j=0
for i in "$2"
do
if [[ "$3" = '1.0' ]]
then
"$4"="PASS"
echo -e "\nA:$3 and T:$i sec" >> "$1"
else
"$4"="FAIL"
echo -e "\nA:$3 and T:$i sec" >> "$1"
fi
j=$(( $j + 1 ))
done
return "$4"
}
result=compare $1 ${A[#]} ${T[#]} output
echo "result:$result"
When I call ./test.sh file.txt, I get the following error:
./test.sh: line 13: output=FAILED: command not found
./test.sh: line 18: return: output: numeric argument required
result=
Lots of problems here:
trying to assign a value to a variable value (this is the cause of the "output=FAIL" error you see)
passing arrays as first-class values
collecting output of the function
It's still not clear how A and T are related (settle down, techbros), but it looks like T contains the index you want to look up in A.
#!/bin/bash
# validate the bash version at least 4.4 here.
function compare(){
local file=$1
local -n arrayA=$2
local -n arrayT=$3
local -n resultVar=$4
resultVar=PASS
for i in "${arrayT[#]}"; do
if [[ "${arrayA[i]}" != '1.0' ]]; then
resultVar=FAIL
# normally I would return here, but you want to log the whole array
fi
printf "A:%f and T:%d sec\n" "${arrayA[i]}" "$i" >> "$file"
done
}
output='PASS'
T=(1 2 3 4 5 6)
A=([1]=1.0 1.0 1.0 1.0 0.0 1.0) # force A to start with index 1, corresponding to the first element of T
compare "$1" A T output
echo "result:$output"
What's wrong with this code? If I input the number 25, it output failed instead of lol. Am I missing something?
read -p "Enter number : " num
if [ `expr $num > 5` ]
then
echo "lol"
else
echo "failed"
fi
The code
if [ `expr $num > 5` ]
actually does not do want you think. It will run expr $num > 5, so evaluate parameter and redirect the out to a file named 5 ("put 25 in a file named 5") and if will evaluate the return code of the previous expression.
If the code if meant to check evaluate if a number is bigger than 5, replace
if [ `expr $num > 5` ]
with
[ "$num" -gt 5 ]
-gt stands for greater than
#babtistemm's answer gives you the suggested solution but in case you insist on using (the bit oldish) expr for some reason:
read -p "Enter number : " num
if expr "$num" '>' 5 >/dev/null
then
echo "lol"
else
echo "failed"
fi
Notes:
You need to quote > so that the shell does not interpret it as redirecting the stdout. You could also use \>.
It is good practice to add double quotes to $num as well, so that expr will interpret it as one expression, thus limiting the chances of a very bad bug or a malicious user hacking your program. (Best would be to do a sanity-check on $num before using it, e.g. checking if it is an integer.)
This solution necessitates calling a new process, expr, which costs a lot more resource from the OS than using the test shell command only.
If you omit the >/dev/null, you will also get a 0 or 1 printed (meaning false or true), the stdout of expr. But independently of that, expr sets its exit status, $? according to the result of the expression, which is tested then by the if. (A side remark: if you try to echo $? after calling expr, it may come at a surprise first that $? = 0 means true/success as exit status, and $? != 0 means false by convention.)
you can use an arithmetic expression in bash:
if (( num > 5 )); then ...
In the manual, see https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructs
Same in a short line:
read -p 'Enter a number: ' num
(( num > 5 )) && echo lol || echo fail
could be condensed:
read -p 'Enter a number: ' num;((num>5))&&echo lol||echo fail
This syntaxe will work if first command success!
read -p 'Enter a number: ' num
((num > 5)) && {
echo lol
/bin/wrongcommand
:
} || echo fail
Could output:
lol
bash: /bin/wrongcommand: No such file or directory
But no fail because of : (is an alias for true) will alway success.
You could of course group command for fail:
read -p 'Enter a number: ' num
((num > 5)) && {
echo lol
/bin/wrongcommand
:
} || {
echo fail
other command
}
Could be written:
read -p 'Enter a number: ' num;((num>5))&&{ echo lol;/bin/wrongcommand;:;}||{ echo fail;other command;}
You could group commands between { and ;} (care about the space after first {!)
Enter a number: 4
fail
bash: other: command not found
Enter a number: 7
lol
bash: /bin/wrongcommand: No such file or directory
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.
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")