2

I am busy making a function that gives the user a yes or no question. However I seem to be making a mistake with my script.

#!/bin/bash
read -p "Test, enter y or n: " choice
echo "$choice"
if [ "$choice"==y ]
then
  echo "you choose $choice"
else
  echo "you did not choose y"
fi

This always seems to return You choose y|n, despite the fact that I expect it to return you did not choose y.

I have been searching for a while now and tried to solve it using double brackets, no brackets, quotes, no quotes.

Jelmergu
  • 973
  • 1
  • 7
  • 19
  • `[[ "$choice" == "y" ]]` – 123 Jan 19 '16 at 10:43
  • 1
    Please don't make scripts interactive without compelling reason; it is not the unix way to invoke programs. Far better is to have a command line option like `my_program -y`. – msw Jan 19 '16 at 11:01
  • @msw that is my intention but for the sake of this example i put it like this, as i discovered that my problem was specifically in this part of the code, no need to put extra 'useless' code here – Jelmergu Jan 19 '16 at 14:23
  • 1
    There are FAQs, and then there are things where **literally exactly this bug** is shown on the tag wiki page, in an example of how to take a bad question and improve it: http://stackoverflow.com/tags/bash/info – Charles Duffy Jan 19 '16 at 15:34
  • @CharlesDuffy Excuse me, I did not see that page, if I did I would not have asked the question – Jelmergu Jan 20 '16 at 08:57

3 Answers3

3

It was a syntax error, you weren't correctly using the operator ==. You must put spaces around your operator. Good practice : put quotes around y so you know it's a literal value and use = rather than == for compatibility reason :

#!/bin/bash
read -p "Test, enter y or n: " choice
echo "$choice"
if [ "$choice" = "y" ]
then
  echo "you choose $choice"
else
  echo "you did not choose y"
fi

I didn't find any satisfying sources, here's is the best I could find :

Community
  • 1
  • 1
Adrien Horgnies
  • 691
  • 4
  • 11
  • 1
    `must double the [] ` , is incorrect. `missing the quotes around y` also incorrect, `your y is a name but you must use the litteral value "y"`, also incorrect. `put spaces around your operator`, is correct and the only problem with OP's code. – 123 Jan 19 '16 at 10:47
  • Well it did work for me. waiting to accept the answer. Would be nice if you could tell me why and/or point me to some reference – Jelmergu Jan 19 '16 at 10:48
  • Well, I partly disagree with you 123. It's true that op didn't need all the changes I suggested but it did what OP was trying to do. If you don't put quotes around y, you're not doing a litteral match. For the rest, you're totally right, my bad. – Adrien Horgnies Jan 19 '16 at 11:17
  • 1
    `If you don't put quotes around y, you're not doing a litteral match`, yes you are, the quotes literally do nothing unless you are using special characters. – 123 Jan 19 '16 at 11:31
  • 3
    Not really any reason to use `==` instead of `=` as it only breaks compatibility with other POSIX shells. – Tom Fenech Jan 19 '16 at 11:38
  • @123 As far as I understand, literal matching means you don't interpret special characters, either there are some or not. I get your point, y would have worked as good as "y" here but it doesn't mean you're doing a literal match. The source I provide specifically explains only "text" does literal matching and no quotes does not. – Adrien Horgnies Jan 19 '16 at 13:32
  • With `[ ... ]`, you *always* perform a literal match of whatever appears on the right-hand side of the `=`. The shell might have expanded the original argument before `[` runs, but that's a separate issue. With `[[ ... = ...]]` (`=` or `==`), the right-hand side is treated as a pattern if it is unquoted. – chepner Jan 19 '16 at 14:09
  • @chepner Please, explain me this line then : [ $a == z* ] # File globbing and word splitting take place. It comes from the source I provide and I don't understand it but it really gives me the impression it is not literal matching. I'd really like to understand as it seems I miss the point. – Adrien Horgnies Jan 19 '16 at 15:21
  • The shell expands `z*` to any matching files before `[` runs. If the current directory has two files `za` and `zb`, then `[` gets 4 arguments; `==`, `za`, `zb`, and `]`. It only gets the argument `z*` if there are no matching files, in which case the shell leaves the pattern unexpanded. `[[ ... ]]`, on the other hand, is a special shell construct, not a regular command. `[[ $foo == z* ]]` compares the value of `$foo` to the pattern `z*`, rather than performing pathname expansion on the pattern first. – chepner Jan 19 '16 at 15:23
  • @chepner Ok, so your point is that it is still a literal match because the shell provides arguments which are used as literal values by the bash script, am I right? If yes, thanks for the explanation. Actually, thanks anyway. – Adrien Horgnies Jan 19 '16 at 15:30
  • That is correct. `[` is treated the same as any other command regarding its arguments (it's easier to see if you think of it as `test $a = z*` instead). `[[` operates under a separate set of rules. – chepner Jan 19 '16 at 15:32
  • 1
    Please consider using a better reference than the ABS -- it has a longstanding and unfortunate habit of showcasing bad practices in its examples. – Charles Duffy Jan 19 '16 at 15:35
0

Add spaces around == and it will work.

#!/bin/bash
read -p "Test, enter y or n: " choice
echo "$choice"
if [ "$choice" == y ]
then
  echo "you choose $choice"
else
  echo "you did not choose y"
fi
Arenlind
  • 53
  • 5
0

You just have to quote the second string "y" and put spaces between string1, the operator and string2.

[…]
if [ "$choice" == "y" ]
[…]

You don't have to double the square brackets.

O.Meta
  • 26
  • 3