Two conditions in a bash if statement - bash

I'm trying to write a script which will read two choices, and if both of them are "y" I want it to say "Test Done!" and if one or both of them isn't "y" I want it to say "Test Failed!"
Here's what I came up with:
echo "- Do You want to make a choice?"
read choice
echo "- Do You want to make a choice1?"
read choice1
if [ "$choice" != 'y' ] && [ "$choice1" != 'y' ]; then
echo "Test Done!"
else
echo "Test Failed!"
fi
But when I answer both questions with "y" it's saying "Test Failed!" instead of "Test Done!". And when I answer both questions with "n" it's saying "Test Done!"
What have I done wrong?

You are checking for the wrong condition.
if [ "$choice" != 'y' ] && [ "$choice1" != 'y' ];
The above statement is true when choice!='y' and choice1!='y', and so the program correctly prints "Test Done!".
The corrected script is
echo "- Do You want to make a choice ?"
read choice
echo "- Do You want to make a choice1 ?"
read choice1
if [ "$choice" == 'y' ] && [ "$choice1" == 'y' ]; then
echo "Test Done !"
else
echo "Test Failed !"
fi

The program is doing exactly what you told it to do. You said "If the first choice is not equal to 'y' and the second choice is not equal to 'y' then print "Test Done !" otherwise print "Test Failed !" -- so only if both choices are not y will "Test Done !" be printed.
You probably meant:
echo "- Do You want to make a choice ?"
read choice
echo "- Do You want to make a choice1 ?"
read choice1
if [ "$choice" == 'y' ] && [ "$choice1" == 'y' ]; then
echo "Test Done !"
else
echo "Test Failed !"
fi
I changed != not equals to == equals. Now only if you answer "y" to both questions will "Test Done !" be printed.

if [ "$choice" != 'y' -a "$choice1" != 'y' ]; then
echo "Test Done !"
else
echo "Test Failed !"
fi

You got the comparison logic backwards; from your description you wanted to say
if [ "$choice" = 'y' ] && [ "$choice1" = 'y' ]; then
I'm actually surprised that the && construct works, although on further inspection it probably should. Still, I would write it as
if [ "$choice" = 'y' -a "$choice1" = 'y' ]; then

You have your logic reversed; you're checking for != when you should be checking for ==. Try this:
if [ "$choice" == 'y' ] && [ "$choice1" == 'y' ]; then
echo "Test Done !"
else
echo "Test Failed !"
fi

Another thought,
$ c1='y' ; c2='y' ; [[ ${c1} = 'y' ]] && [[ ${c2} = 'y' ]] && echo true || echo false
true
$ c1='n' ; c2='y' ; [[ ${c1} = 'y' ]] && [[ ${c2} = 'y' ]] && echo true || echo false
false
$ c1='n' ; c2='y' ; [[ ${c1} = 'y' ]] || [[ ${c2} = 'y' ]] && echo true || echo false
true
$ c1='n' ; c2='n' ; [[ ${c1} = 'y' ]] || [[ ${c2} = 'y' ]] && echo true || echo false
false
$
Overflow of gibberish. (;

Try:
if [[ "$choice" != 'y' && "$choice1" != 'y' ]]; then
echo "Test Done!"
else
echo "Test Failed!"
fi

The line
if [ "$choice" != 'y' ] && [ "$choice1" != 'y' ]; then
tests if both choices aren't 'y', so when both choices are 'y', the statement is false and your program correctly prints "Test Failed".

Related

if else statement in a while command is not working... BASH

#!/bin/sh
#datafile
#script
while echo enter name
read -r code
do
if [ "$code" = 'STOP' ];
then
break
else
grep "$code" datafile > outputres
while echo ' Would you like to see B OR R'
read -r answer
do
if [[ "$answer" = 'B' && "$code" = datafile ]];
then
echo show B.
break
elif [[ "$answer" = 'R' && "$code" = datafile ]];
then
echo show R
break
elif [[ "$answer" = 'B' && "$code" != datafile ]];
then
echo No such THING.
break
elif [[ "$answer" = 'R' && "$code" != datafile ]];
then
echo No such THING.
break
else :
echo Enter only B or R.
fi
done
fi
done
echo Goodbye!
Hello, I hope someone can help. but I'm having some issues when I execute my program I receive "no such thing" when it should display "show r".
UPDATE: I changed code to a number found in the data and it works, so I need a better way to say ("$code" = filename) number is in data or not in the data.
btw I have also checked if i have any errors and I dont

Is there a better solution to this if statement problem?

Bash function to execute a git pull in all subfolder where a .git directory is found.
I'm having issues with the last elif.
This part:
...
elif [ $answer == '' || $answer -ne 'y' || $answer -ne 'n' ] ; then
echo '---Please answer with y/n---'
...
Whole code of the function:
dogitpull () {
for i in */.git; do ( echo $i; cd $i/..; ); done
echo -n 'Are you sure? (y/n) '
read answer
echo $answer
if [ $answer == 'n' ] ; then
echo '---CANCELED---'
elif [ $answer == 'y' ] ; then
echo '---------------------------'
for d in */.git; do ( echo $d; cd $d/..; git pull; echo '---------------------------'; ); done
elif [ $answer == '' || $answer -ne 'y' || $answer -ne 'n' ] ; then
echo '---Please answer with y/n---'
fi
}
If the answer is empty (pressed enter), is not 'y' or is not 'n' there should be the text "Please answer with y or n" and should start again from the "read answer".
Does anybody have a solution to this?
Output: when pressing enter
-bash: [: ==: unary operator expected
-bash: [: ==: unary operator expected
-bash: [: missing `]'
-bash: -ne: command not found
-bash: -ne: command not found
Output: when entering something else than y or n
-bash: [: missing `]'
-bash: a: command not found
-bash: a: command not found
use case. example:
#!/bin/bash
echo -n 'Are you sure? (y/n) '
read answer
echo $answer
case "$answer" in
n|N) echo '---CANCELED---';;
y|Y) echo '-- yes ---';;
*) echo '---Please answer with y/n---';;
esac
The problem here is that you didn't quote the variable. When $answer is empty then [ $answer == '' ] expands to [ == '' ] which gives an error since there is nothing on the left hand side of the ==.
Fix
Quote your your variable and then proceed to fix the following errors (courtesy of Kamil Cuk):
-ne is for numbers, it will error with "Integer expression expected". Use != instead.
|| is not valid for [. Use -o or put the || outside the braces: [ ... ] || [ ... ] || [ .. ]
elif [ "$answer" = '' ] || [ "$answer" != 'y' ] || [ "$answer" != 'n' ]
Improvements
Use a single = instead of ==. [ a = b] is the official and portable way to check equality of a and b.
Instead of elif [ "$answer" == '' || "$answer" -ne 'y' || "$answer" -ne 'n' you may want to write just else which has the samme effect due to the preceding if-cases.
if [ "$answer" = 'n' ] ; then
# ...
elif [ "$answer" = 'y' ] ; then
# ...
else
# ...
fi
If answer is not a y and it is not an n, then you need to take action.
elif [ "$answer" != 'y' ] && [ "$answer" != 'n' ]; then
echo '---Please answer with y/n---'
Or you can do Moore's law and:
If not both: answer is 'Y' or answer is 'n', then you need to take action.
elif ! { [ "$answer" = 'y' ] || [ "$answer" = 'n' ]; }; then
echo '---Please answer with y/n---'
or with a ( subshell:
elif ! ( [ "$answer" = 'y' ] || [ "$answer" = 'n' ] ); then
echo '---Please answer with y/n---'

How to do character comparison in bash scripts?

Here is my code
#! /bin/bash
read var
if [ $var="Y" -o $var="y" ]
then
echo "YES"
else
echo "NO"
fi
I want to print YES if the user presses y or Y, otherwise I want to print NO. Why doesn't this code work?
Basically, your Condition is wrong. Quote your variables and leave spaces between operators (like shellter wrote). So it should look like:
#! /bin/bash
read var
if [ "$var" = "Y" ] || [ "$var" = "y" ]
then
echo "YES"
else
echo "NO"
fi
Edit: for POSIX ccompatibility
Replaced == with = - see comments
Replaced -o syntax with || syntax - see comments
With Bash, you can also use regular expression in your test with the =~ operator:
read var
[[ "$var" =~ [Yy] ]] && echo "YES" || echo "NO"
Or as Benjamin W. mentionned, simply use character range with the == operator:
read var
[[ "$var" == [Yy] ]] && echo "YES" || echo "NO"
There is minor syntax error in your code.
Correction : There should be a white space between operators and variables
read var
if [ $var = "Y" -o $var = "y" ]
then
echo "YES"
else
echo "NO"
fi
Try the above bash script.
Hope it would work fine.
Happy Coding!
If all you require is a upper/lowercase comparison, use the ,, operator on the variable being compared ( note the ${var,,} ):
#!/bin/bash
read var
if [ ${var,,} = "y" ]
then
echo "YES"
else
echo "NO"
fi
or more succinctly:
#!/bin/bash
read var
[ ${var,,} = 'y' ] && echo 'YES' || echo 'NO'
or the way I might actually do it:
#!/bin/bash
read var
[[ "${var,,}" == 'y' ]] && echo 'YES' || echo 'NO'
Below is the code that I tried.
#! /bin/bash
read -p "Are you Sure?(Y/N) " answer
if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then
echo "Do your stuff."
else
echo "Do your other stuff"
fi
Add whitespace around '=' and your code will run fine.
#! /bin/bash
read var
if [ $var = "Y" -o $var = "y" ]
then
echo "YES"
else
echo "NO"
fi
Try this code.
#! /bin/bash
read var
echo -e "YES\nNO\n" | grep -i $var

Comparing Strings in Bash with Logical Or

I'm having an issue getting a a simple y/n question to work. Consider the following code:
echo "Hi there"
read ans
if [[ $ans != "y" || $ans != "Y" || $ans != "YES" || $ans != "yes" ]]; then
echo "Foo"
exit 0
fi
I've looked at – I would argue – some of the more informative answers on StackOverflow for advice: Simple logical operators in Bash
I've tried all different types of variations such as:
if [[ ($ans != "y" || $ans != "Y" || $ans != "YES" || $ans != "yes") ]]; then
echo "Foo"
exit 0
fi
if [[ ($ans != "y*" || $ans != "Y*" || $ans != "YES*" || $ans != "yes*") ]]; then
echo "Foo"
exit 0
fi
if [[ ($ans != "y") || ($ans != "Y") || ($ans != "YES") || ($ans != "yes") ]]; then
echo "Foo"
exit 0
fi
Regardless of why I type in any of these cases, it automatically fails and I'm not sure why. If anyone has a better way to handle y/n answers then please let me know! Ideally I would like to use pattern matching (like I might do with Perl) but I'm not entirely sure the best way/most efficient way to accomplish a simple y/n question.
You need to use && instead of ||. As it stands you're saying if it's not equal to any of those possibilities, then execute the "then" block. You mean to say if it's not equal to all of them, then execute the "then" block. That requires &&.
You can use:
echo "Hi there"
read ans
case "$ans" in
y|Y|YES|yes)
;;
*)
echo "Foo"
exit 0
;;
esac
The logic needs to be adjusted:
echo "Hi there"
read ans
if ! [[ "$ans" == "y" || "$ans" == "Y" || "$ans" == "YES" || "$ans" == "yes" ]]; then
echo "Foo" # User answered no
exit 0
fi
The will echo "Foo" only if the answer was not one of "y", "Y" or "YES". By contrast, consider the original logic:
[[ $ans != "y" || $ans != "Y" || $ans != "YES" || $ans != "yes" ]]
At least one of these tests will be true regardless of what the user's answer is.
Using the case statement
You might consider using the case statement to analyze the user's answer:
read -p "Hi there: " ans
case "$ans" in
[yY]*) ;;
[nN]*) echo "Foo" ; exit 0 ;;
*) echo "You were supposed to answer yes or no" ;;
esac
Try read ans, not read $ans.

bash if logical boolean string

I am not looking for a different way to accomplish the apparent intention. I'm looking to understand why this exact syntax is not working.
[root#lvs ~]# while true;do
> echo "Would you like the script to check the second box ([y]n)?"
> read ans
> if [ "$ans" == "n" ];then
> echo
> echo "bye"
> exit
> elif [ "$ans" != "" -o "$ans" != "y" ];then
> echo "Invalid entry..."
> else
> break
> fi
> done
Would you like the script to check the second box ([y]n)? **"Should have continued"**
Invalid entry...
Would you like the script to check the second box ([y]n)? **"Should have continued"**
y
Invalid entry...
Would you like the script to check the second box ([y]n)? **"Correct behavior"**
alskjfasldasdjf
Invalid entry...
Would you like the script to check the second box ([y]n)? **"Correct behavior"**
n
bye
Here's a reference that's identical to so many others i found. I understand what it's doing, it's using the non logical's for AND and OR when everything I've read said that it should be using logical bools.
http://www.groupsrv.com/linux/about140851.html
Ok so here it is, with Nahuel's suggestion behaving how I had originally expected it to:
[root#lvs ~]# while true;do
> echo "Would you like the script to check the second box ([y]n)?"
> read ans
> if [ "$ans" = "n" ];then
> echo
> echo "bye!"
> exit
> elif [ "$ans" != "" -a "$ans" != "y" ];then
> echo "Invalid entry..."
> else
> break
> fi
> done
Would you like the script to check the second box ([y]n)?
asdfad
Invalid entry...
Would you like the script to check the second box ([y]n)?
[root#lvs ~]# while true;do
> echo "Would you like the script to check the second box ([y]n)?"
> read ans
> if [ "$ans" = "n" ];then
> echo
> echo "bye!"
> exit
> elif [ "$ans" != "" -a "$ans" != "y" ];then
> echo "Invalid entry..."
> else
> break
> fi
> done
Would you like the script to check the second box ([y]n)?
y
[root#lvs ~]# while true;do
> echo "Would you like the script to check the second box ([y]n)?"
> read ans
> if [ "$ans" = "n" ];then
> echo
> echo "bye!"
> exit
> elif [ "$ans" != "" -a "$ans" != "y" ];then
> echo "Invalid entry..."
> else
> break
> fi
> done
Would you like the script to check the second box ([y]n)?
n
logout
The problem is that : [ "$ans" != "" -o "$ans" != "y" ] is always true because of the or and the negation. $ans cannot be equal to "" and to "y".
Try replace these lines
if [ "$ans" == "n" ];then
elif [ "$ans" != "" -o "$ans" != "y" ];then
by these
if [ "$ans" = "n" ];then
elif [ "$ans" != "" -a "$ans" != "y" ];then
or these
if [[ $ans == n ]];then
elif [[ $ans != "" && $ans != y ]];then
The easier is to do is a case:
case $ans in
y) echo "yes"
;;
n) echo "no"
;;
*)
;;
esac
also break must be used only in a for or while loop, or in a select but it is missing in your post .
I don't really understand, why do you use -o in the elif. I would use "||" or "OR" operator. When you use two conditions in if, you should use double [[ and ]].
So if you use:
elif [[ "$ans" != "" || "$ans" != "y" ]];then
it works fine.
also logically its a flawed way of doing things.
firstly using case would be best in this scenario, secondly you are looking for == n then stating if it is blank or not equal to yes - so although no is caught out in first if statement in theory it would still meet second criteria
surely the most logical way to ensure input is 100% would be
if [ "$ans" == "n" ];then
echo
echo "bye"
exit
elif [ "$ans" == "y" ];then
echo Yes
break;
else
echo "Invalid entry... >$ans<"
fi

Resources