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
Related
This question already has answers here:
How do I prompt for Yes/No/Cancel input in a Linux shell script?
(37 answers)
Closed 28 days ago.
How do I ask a yes/no type question in Bash?
I ask the question... echo "Do you like pie?"
And receive the answer... read pie
How do I do something if the answer is yes, or starts with y (so yes and yeah, etc, will work too).
I like to use the following function:
function yes_or_no {
while true; do
read -p "$* [y/n]: " yn
case $yn in
[Yy]*) return 0 ;;
[Nn]*) echo "Aborted" ; return 1 ;;
esac
done
}
So in your script you can use like this:
yes_or_no "$message" && do_something
In case the user presses any key other than [yYnN] it will repeat the message.
This works too:
read -e -p "Do you like pie? " choice
[[ "$choice" == [Yy]* ]] && echo "doing something" || echo "that was a no"
Pattern starting with Y or y will be taken as yes.
I like Jahid's oneliner. Here is a slight simplification of it:
[[ "$(read -e -p 'Continue? [y/N]> '; echo $REPLY)" == [Yy]* ]]
Here are some tests:
$ [[ "$(read -e -p 'Continue? [y/N]> '; echo $REPLY)" == [Yy]* ]] && echo Continuing || echo Stopping
Continue? [y/N]> yes
Continuing
$ for test_string in y Y yes YES no ''; do echo "Test String: '$test_string'"; echo $test_string | [[ "$(read -e -p 'Continue? [y/N]>'; echo $REPLY)" == [Yy]* ]] && echo Continuing || echo Stopping; done
Test String: 'y'
Continuing
Test String: 'Y'
Continuing
Test String: 'yes'
Continuing
Test String: 'YES'
Continuing
Test String: 'no'
Stopping
Test String: ''
Stopping
Update
In response to a comment, I'm going to add an adaptation to make this work in zsh.
Disclaimer
I would never write a shell script in zsh even though it is now my primary interactive shell. I still write all scripts in bash or sh. However, since you sometimes need to script modifications to your interactive shell (ex: source ~/dev/set_env), you might want to include prompting.
#! /usr/bin/env zsh
[[ "$(echo -n 'Continue? [y/N]> ' >&2; read; echo $REPLY)" == [Yy]* ]] \
&& echo Continuing \
|| echo Stopping
This works:
echo "Do you like pie?"
read pie
if [[ $pie == y* ]]; then
echo "You do! Awesome."
else
echo "I don't like it much, either."
fi
[[ $pie == y* ]] tests to see of the variable $pie starts with y.
Feel free to make this better if you'd like.
In contrast to the other answers this function gives you the possibility to set a default:
function askYesNo {
QUESTION=$1
DEFAULT=$2
if [ "$DEFAULT" = true ]; then
OPTIONS="[Y/n]"
DEFAULT="y"
else
OPTIONS="[y/N]"
DEFAULT="n"
fi
read -p "$QUESTION $OPTIONS " -n 1 -s -r INPUT
INPUT=${INPUT:-${DEFAULT}}
echo ${INPUT}
if [[ "$INPUT" =~ ^[yY]$ ]]; then
ANSWER=true
else
ANSWER=false
fi
}
askYesNo "Do it?" true
DOIT=$ANSWER
if [ "$DOIT" = true ]; then
< do some stuff >
fi
On the command line you would see
Do it? [Y/n] y
Here is a short function:
prompt(){ read -p "$1" a; return $(test $a = "y"); }
Usage (if the answer is y then do_something executed):
prompt "Do you want it?" && do_something
Usage with multiple commands:
prompt "Do you want it?" && {
do_something1
do_something2
}
I've written below code, but it won't work for SPACE,special symbols etc.
I want my script to exit if any key pressed on keyboard apart from Y/y.
It should handle SPACEBAR,special symbols
echo "enter y, any other key to exit "
read input
if [ $input != "Y" -o $input = "y" ]; then
echo "Exiting"
fi
if [ $input == "Y" -o $input == "y" ]; then
echo "Working"
fi
See http://wiki.bash-hackers.org/commands/builtin/read?s[]=read
Normally you always want to use the -r flag. -n 1 tells read to only read 1 character.
asksure() {
echo -n "Are you sure (Y/N)? "
while read -r -n 1 -s answer; do
if [[ $answer = [YyNn] ]]; then
[[ $answer = [Yy] ]] && retval=0
[[ $answer = [Nn] ]] && retval=1
break
fi
done
echo # just a final linefeed, optics...
return $retval
}
### using it
if asksure; then
echo "Okay, performing rm -rf / then, master...."
else
echo "Pfff..."
fi
First, you need to quote the parameter expansions to make sure certain inputs are not removed altogether during word splitting and quote removal.
You are using the wrong operator. No matter what key you type, one of not Y and not y will be true. For example, "Y" != "y". You want to use and instead of or.
if [ "$input" != "Y" ] && [ "$input" != "y" ]; then
The boolean operators -o and -a are no longer recommended, due to ambiguities than can arise from their use. Use separate test commands joined by || and && (respectively) instead.
You need to put $input in quotes, so the statement parses properly. If your response is a space, what the script sees is
if [ != "Y" -o != "y" ]; then
Which it obviously can't parse properly.
Use
if [ "$input" != "Y" -o "$input" = "y" ]; then
and you should be OK.
By the way, you don't actually exit if the condition is met. Add a return after the echo "Exiting" line.
I am attempting to run a block of code if one flag is set to true and the other is set to false. ie
var1=true
var2=false
if [[ $var1 && ! $var2 ]]; then var2="something"; fi
Since that did not evaluate the way that I expected I wrote several other test cases and I am having a hard time understanding how they are being evaluated.
aa=true
bb=false
cc="python"
if [[ "$aa" ]]; then echo "Test0" ; fi
if [[ "$bb" ]]; then echo "Test0.1" ; fi
if [[ !"$aa" ]]; then echo "Test0.2" ; fi
if [[ ! "$aa" ]]; then echo "Test0.3" ; fi
if [[ "$aa" && ! "$bb" ]]; then echo "Test1" ; fi
if [[ "$aa" && ! "$aa" ]]; then echo "Test2" ; fi
if [[ "$aa" ]] && ! [[ "$bb" ]]; then echo "test3" ; fi
if [[ "$aa" ]] && ! [[ "$cc" ]]; then echo "test4" ; fi
if [[ $aa && ! $bb ]]; then echo "Test5" ; fi
if [[ $aa && ! $aa ]]; then echo "Test6" ; fi
if [[ $aa ]] && ! [[ $bb ]]; then echo "test7" ; fi
if [[ $aa ]] && ! [[ $cc ]]; then echo "test8" ; fi
When I run the preceding codeblock the only output I get is
Test0
Test0.1
Test0.2
however, my expectation is that I would get
Test0
Test1
Test3
Test5
Test7
I have tried to understand the best way to run similar tests, however most examples I have found are set up in the format of
if [[ "$aa" == true ]];
which is not quite what I want to do. So my question is what is the best way to make comparisons like this, and why do several of the test cases that I would expect to pass simply not?
Thank you!
Without any operators, [[ only checks if the variable is empty. If it is, then it is considered false, otherwise it is considered true. The contents of the variables do not matter.
Your understanding of booleans in shell context is incorrect.
var1=true
var2=false
Both the above variables are true since those are non-empty strings.
You could instead make use of arithmetic context:
$ a=1
$ b=0
$ ((a==1 && b==0)) && echo y
y
$ ((a==0 && b==0)) && echo y
$
$ ((a && !(b))) && echo y; # This seems to be analogous to what you were attempting
y
The shell does not have Boolean variables, per se. However, there are commands named true and false whose exit statuses are 0 and 1, respectively, and so can be used similarly to Boolean values.
var1=true
var2=false
if $var1 && ! $var2; then var2="something"; fi
The difference is that instead of testing if var1 is set to a true value, you expand it to the name of a command, which runs and succeeds. Likewise, var2 is expanded to a command name which runs and fails, but because it is prefixed with ! the exit status is inverted to indicate success.
(Note that unlike most programming languages, an exit status of 0 indicates success because while most commands have 1 way to succeed, there are many different ways they could fail, so different non-zero values can be assigned different meanings.)
true and false are evaluated as strings ;)
[[ $var ]] is an equivalent of [[ -n $var ]] that check if $var is empty or not.
Then, no need to quote your variables inside [[. See this reminder.
Finally, here is an explication of the difference between && inside brackets and outside.
The closest you can come seems to be use functions instead of variables because you can use their return status in conditionals.
$ var1() { return 0; }
$ var2() { return 1; } # !0 = failure ~ false
and we can test this way
$ var1 && echo "it's true" || echo "it's false"
it's true
$ var2 && echo "it's true" || echo "it's false"
it's false
or this way
$ if var1; then echo "it's true"; else echo "it's false"; fi
it's true
$ if var2; then echo "it's true"; else echo "it's false"; fi
it's false
Hope this helps.
I try to test if a string starts with a certain prefix. But my script seems not work (I would expect the "if" branch will not get run). Can some Bash expert help to take a look? thanks!
Here is my code and test result:
$ cat testb.bash
#!/bin/bash
my_var="abcdefg";
if [[ "${my_var:0:5}"=="order" ]]; then
echo "value of my_var is ${my_var}.";
fi;
if [[ "${my_var:0:5}" -eq "order" ]]; then
echo "value of my_var is ${my_var}.";
fi;
if [ "${my_var:0:5}"="order" ]; then
echo "value of my_var is ${my_var}.";
fi;
$ bash -x testb.bash
+ my_var=abcdefg
+ [[ -n abcde==order ]]
+ echo 'value of my_var is abcdefg.'
value of my_var is abcdefg.
+ [[ abcde -eq order ]]
+ echo 'value of my_var is abcdefg.'
value of my_var is abcdefg.
+ '[' abcde=order ']'
+ echo 'value of my_var is abcdefg.'
value of my_var is abcdefg.
$
Whitespace is significant in this case. As you can see in the -x output, it understands the first condition as
[[ -n "${my_var:0:5}==order" ]]
Moreover, to test for a prefix, you can use a pattern:
[[ $my_var == order* ]]
To test the existence of substring, you can use either of these:
if [[ "$j" =~ string1 ]]; then
if [[ $j == *string1* ]]; then
In your particular case, you miss a space surounding ==, so instead of
if [[ "${my_var:0:5}"=="order" ]]; then
it should be
if [[ "${my_var:0:5}" == "order" ]]; then
^ ^
Finally, note that your condition was evaluated as true because it was evaluating if [ "string" ], which is true if string is not empty:
$ [ "a" ] && echo "yes"
yes
Test
$ cat a
#!/bin/bash
my_var="abcdefg";
if [[ "${my_var:0:5}" == "order" ]]; then
echo "value of my_var is ${my_var}."
elif [[ "${my_var:0:5}" == "abcde" ]]; then
echo "yeahaa"
else
echo "is not"
fi
$ ./a
yeahaa
Ok, i tested your code, you shoud such as the following code:
prefix="pre_order";
pre="pre_"
len=${#pre}
echo $len
if [[ "${prefix:0:len}" == "blahvlah" ]] ; then
echo "dddd"
fi;
Notes:
use == for string comparation
for ${} you should initilize a string variable before ${}
use len=${#pre} for lenght of string.
A POSIX-compliant way to test for a prefix is to attempt to remove the prefix, and compare the result to the original string. If the two are the same, the prefix is not present, the removal fails, and the expression expands to the original string.
prefix=foo
string=foobar
if [ "${string#$prefix}" = "$string" ]; then
printf "$string does not start with $prefix\n"
else
printf "$string starts with $prefix\n"
fi
Hi I have the script as below.
if [[ 'whoami' -eq "test" ]]; then
echo "test user"
else
echo "Not a test user"
fi
This is returning test user even if my user is not text. It would be great if someone can pin point my silly mistake.
-eq is for integer testing.
e.g.:
kent$ [[ "a" -eq "b" ]] && echo "y" || echo "n"
y
kent$ [[ 34 -eq 35 ]] && echo "y" || echo "n"
n
try:
kent$ [[ "a" == "b" ]] && echo "y" || echo "n"
n
You are using single quotes in place of backticks:
if [[ `whoami` -eq "test" ]]; then # Not 'whoami'
For improved readability (and easier nesting, if applicable), use
if [[ $(whoami) -eq "test" ]]; then
instead.
Just like this:
if [[ `whoami` == "test" ]]; then # Not 'whoami' -eq
echo "test user"
else
echo "Not a test user"
fi
don't use single quote and '-eq'