checking if argument passed equals a string in bash script - bash

Little explanation necessary: why the hell does this doesn't work?
#!/bin/bash
ker=$1
if [ "$ker" != "iso" ] || [ "$ker" != "om" ] || [ "$ker" != "constbeta" ] ; then
printf " allowed kernels: iso, om, constbeta \n"
exit
fi
wait
echo 'anisotropy kernel: ', "$ker"
I have also tried
#!/bin/bash
ker="$1"
if [ $ker != "iso" ] || [ $ker != "om" ] || [ $ker != "constbeta" ] ; then
printf " allowed kernels: iso, om, constbeta \n"
exit
fi
wait
echo 'anisotropy kernel: ', "$ker"
I call it like this: $ ./script.sh iso
and I've even tried like this (though I think this doesn't make sense with the
scripts above): $ ./script.sh "iso"
I always get allowed kernels: iso, om, constbeta
Many thanks to those who can spot the error.

because of the logical or ||, you should use and && otherwise the condition is always true thinking to the negation string can't be equals to the three value.

You've got an irrational condition...
if [ "$ker" != "iso" ] || [ "$ker" != "om" ] || [ "$ker" != "constbeta" ] ; then
If $ker is "iso", then it is not "om" and the condition matches. If $ker is "om" then it is not "iso" and the condition matches. What you want is to OR a list of positive checks and have an "else" condition, rather than OR the negative checks.
if [ "$ker" = "iso" ] || [ "$ker" = "om" ] || [ "$ker" = "constbeta" ] ; then
: do something useful
else
: report error
fi
Or, since you're in bash, you could use a "simpler" condition:
if [[ "$ker" =~ ^(iso|om|constbeta)$ ]]; then
Though if you like you could use other constructs:
case "$ker" in
iso|om|constbeta)
: this catches our "good" values
;;
*)
echo "Error" >&2
exit 1
;;
esac
This has the possible benefit of being POSIX compliant.

Related

while loop does not exit when the condition is not met

When running the code below, I’d like to read a user-input answer until it is one of the 6 possible answers ([abcABC]), else continue with the next loop.
However, it does not exit the while loop when I enter one of the accepted answers.
I tried [] and [[]] for the conditions, I tried to place all of the conditions into one pair of square brackets, I tried to use | and ||, none of them worked as expected.
while [ "$ans" != "a" ] || [ "$ans" != "A" ] || [ "$ans" != "b" ] || \
[ "$ans" != "B" ] || [ "$ans" != "c" ] || [ "$ans" != "C" ]; do
read ans
case $ans in
[aA]) echo "aA" ;;
[bB]) echo "bB" ;;
[cC]) echo "cC" ;;
*) echo "Try again." ;;
esac
done
It should read in loop until one of the accepted answer is given; then it should continue with the following code (if any).
Your loop condition is always true, and Bash correctly loops forever.
Consider a simplified version:
[ "$ans" != "a" ] || [ "$ans" != "b" ]
If ans is a then it becomes false || true which is true.
If ans is b then it becomes true || false which is true.
If ans is x then it becomes true || true which is true.
You wanted && instead of ||. Alternatively, do it in a single comparison: [[ "$ans" != [aAbBcC] ]]

Bash if... then... syntax error

I am trying to remove something based on user input using bash/sh, here is my code :
echo "remove ? [Y/n]"
read REMOVE
if [ $REMOVE != "n" ] || [ $REMOVE !="N" ];then
# ... do something ...
echo "done"
fi
the error I am getting is something like:
./run.sh: line 8: syntax error near unexpected symbol « then »
./run.sh: line 8: `if [ $REMOVE != "n" ] || [ $REMOVE !="N" ];then'
I tried to add/remove spaces many times, and I still don't understand what happens. I also don't really understand all the differences between [[ statement ]] [statement] or ((statement)).
If someone can help...
In your original problem, you need a space here
$REMOVE != "N"
In your comment response to shruti1810, it sounds like your $REMOVE variable doesn't contain what you think it contains.
Try adding
echo $REMOVE
to your script.
I typically use this construct
if [ "x$REMOVE" != "xn" ] || [ "x$REMOVE" != "xN" ]
then
# ... do something ...
echo "done"
fi
to ensure that my arguments are both valid.
Please try this:
echo "remove ? [Y/n]"
read REMOVE
if [ $REMOVE != "n" ] && [ $REMOVE != "N" ]
then
# ... do something ...
echo "done"
fi
Quote the "$REMOVE" and insert space around the "!=" -- like this;
if [ "$REMOVE" != "n" ] || [ "$REMOVE" != "N" ];then
# ... do something ...
echo "done"
fi
The problem is that is REMOVE is not set or if it is set to an empty string (like if you just press return on the 'read') you will get $REMOVE substituted to nothing and your expression would look like [ != "N" ] which will produce an unary operator expected error.

Shellscript missing ]

I have a shellscript that tells me missing ] in the line
if [ $status != "2" && $status != "3" && `echo "$temp1 > $upperLimit" | bc` = "1" ]
and also missing ] in the line
if [ $status = "2" && `cat motionsensordate` \> `date +%s` ]
Why is that?
The single [ doesn't support logical operators inside the brackets. You have to use them outside
if [ "$status" != 2 ] && [ "$status" != 3 ] ...
Use double quotes for variables in single brackets to prevent unary operator expected error when the variable is empty.
Or, switch to double brackets:
if [[ $status != 2 && $status != 3 ... ]]
Also, status different to 2 and 3 can be expressed by a pattern:
if [[ $status != [23] && ... ]]
And if you would like to (in addition to the answers here) group together conditions:
if [[ ( COND1 || COND2 ) && COND3 ]]
then
echo "$cmd"
break
fi

Error executing shell script

I am trying to execute the following shell script
#!/bin/sh
echo "start"
if [ $# != 2 || $1 != "first" || $1 != "second" ]
then
echo "Error"
fi
echo "done"
and I'm getting the following output:
start
./autobuild.sh: line 3: [: missing `]'
./autobuild.sh: line 3: !=: command not found
./autobuild.sh: line 3: !=: command not found
done
I have no idea how to resolve the errors. Even if I use -ne instead of !=, I get the same errors. Please help.
Your syntax is incorrect. If you want multiple conditions in an if statement you need to have multiple [] blocks. Try:
if [ $# != 2 ] || [ $1 != "first" ] || [ $1 != "second" ]
But, it's better to use [[ (if your shell supports it) as it is safer to use. I would go for:
if [[ $# -ne 2 || $1 != "first" || $1 != "second" ]]
See this question on brackets: Is [[ ]] preferable over [ ] in bash scripts?
While OR ing the conditions should be seperate as follows :
#!/bin/sh
echo "start"
if [ $# != 2] || [ $1 != "first" ] || [ $1 != "second" ]
then
echo "Error"
fi
echo "done"
Try substituting -NE for !=.
if-usage samples
This should work:
#!/bin/sh
echo "start"
if [ $# -ne 2 -o $1 -ne "first" -o $1 -ne "second" ]
then
echo "Error"
fi
echo "done"

Consolidate multiple if statements in Ksh

How can I consolidate the following if statements into a single line?
if [ $# -eq 4 ]
then
if [ "$4" = "PREV" ]
then
print "yes"
fi
fi
if [ $# -eq 3 ]
then
if [ "$3" = "PREV" ]
then
print "yes"
fi
fi
I am using ksh.
Why does this give an error?
if [ [ $# -eq 4 ] && [ "$4" = "PREV" ] ]
then
print "yes"
fi
Error:
0403-012 A test command parameter is not valid.
Try this:
if [[ $# -eq 4 && "$4" == "PREV" ]]
then
print "yes"
fi
You can also try putting them all together like this:
if [[ $# -eq 4 && "$4" == "PREV" || $# -eq 3 && "$3" == "PREV" ]]
then
print "yes"
fi
Do you just want to check if the last argument is "PREV"? If so, you can also do something like this:
for last; do true; done
if [ "$last" == "PREV" ]
then
print "yes"
fi
'[' is not a grouping token in sh. You can do:
if [ expr ] && [ expr ]; then ...
or
if cmd && cmd; then ...
or
if { cmd && cmd; }; then ...
You can also use parentheses, but the semantics is slightly different as the tests will run in a subshell.
if ( cmd && cmd; ); then ...
Also, note that "if cmd1; then cmd2; fi" is exactly the same as "cmd1 && cmd2", so you could write:
test $# = 4 && test $4 = PREV && echo yes
but if your intention is to check that the last argument is the string PREV, you might consider:
eval test \$$# = PREV && echo yes
Try this :
if [ $# -eq 4 ] && [ "$4" = "PREV" ]
then
print "yes"
fi

Resources