4

I'm attempting to loop through an array of strings, and do something a little different with one of the values. The string comparison fails on every element.

arr[0]='red'
arr[1]='blue'
arr[2]='yellow'
arr[3]='green'

## now loop through the above array
for i in "${arr[@]}"
do
        if [ "$i"="green" ];
        then
                echo "i('$i') is equal to green"
        else
                echo "i('$i') is not equal to green"
        fi

done

I've also tried (with the same result):

if [ "$i"='green' ];

and

if [ $i='green' ];

and

if [ $i="green" ];

Output of each of the above:

i('red') is equal to green
i('blue') is equal to green
i('yellow') is equal to green
i('green') is equal to green

What am I doing wrong with the comparison?

1
  • I see that four people have marked this for closure. There are also four upvotes, so clearly others think it is on-topic. Could someone please instruct me where questions of this nature belong? There is a /bash tag so I assumed this was acceptable use of the sub.
    – a coder
    Oct 1, 2015 at 14:28

4 Answers 4

16

Missing whitespace.

[ $i="green" ] means [ -n $i=green ]

you need

[ "$i" = green ]

or even

[ green = "$i" ]

which works even for i=-n.

If you don't need portability to other shells, you can use double square brackets in bash.

[[ $i = green ]]

Quotes are not needed (in fact, on the right hand side they have a special meaning - they prevent expansion). You can use == instead of =, too.

6
  • Should that be [ "$i" = "green" ]? (EDIT, just tested - it works fine without quotes around green.)
    – a coder
    Sep 30, 2015 at 20:08
  • 2
    @acoder: no need to quote green, there are no special characters.
    – choroba
    Sep 30, 2015 at 20:11
  • 1
    Better to do [ green = "$i" ]. That avoids errors if i contains something like -n. This is a good general practice, because that can make some shells choke. (This is the reason why you'll sometimes see [ "x$a" = "x$b" ].) Bash is a bit smarter about this, but I don't know if it's smarter when using single [ ... ] as opposed to [[ ... ]].
    – dubiousjim
    Oct 1, 2015 at 2:19
  • @dubiousjim - seconded. it's always better to lead with the known value.
    – mikeserv
    Oct 1, 2015 at 2:23
  • @dubiousjim Yes, bash is smarter. [[ $i = green ]] works correctly even unquoted with any -n or similar. There is no word-splitting inside [[ ... ]] in bash.
    – user79743
    Oct 1, 2015 at 7:00
5

You need space around the = comparison operator:

if [ "$i" = "green" ];
3

The reason you need spaces around the = is that the [ and test commands do different things depending on how many arguments you pass. When you only pass a single argument ([ "$i"=green ]), then the result is true if the string is non-empty.

Your code and your output do not match: given the code you posted, every colour should result in i('colour') is equal to green

2
2
[ green = "$i" ]
printf "( '%s' ) is %.$?0sequal to green.\n" "$i" "not "

...would also work.

3
  • Cool stuff. Care sharing how does %.$?0s (if I got the magic right) work?
    – h.j.k.
    Oct 1, 2015 at 2:05
  • Ah, found it: "Field and printing modifiers" - The dot: Together with a field width, the field is not expanded when the text is longer, the text is truncated instead. "%.s" is an undocumented equivalent for "%.0s", which will force a field width of zero, effectively hiding the field from output.
    – h.j.k.
    Oct 1, 2015 at 2:07
  • 2
    @h.j.k - $? expands to the [ test ] command's return - which is generally 1 or 0. It might also be 2 or something else, but in those cases it's gonna let you know on stderr anyway. So when the command expands when green = "$i" it is printf "... %.00s" and when it doesn't it is printf "... %.10s" which tells printf it can use at maximum either 0 or 10 characters from its second argument.
    – mikeserv
    Oct 1, 2015 at 2:08

Not the answer you're looking for? Browse other questions tagged .