Bash does into unexpected recursion when processing expression inside [[ - bash

I am trying to understand the logic of Bash algorithm.
When I tried this, it printed "a":
a=a;[ $a == "a" ] && echo $a
So far so good. Then I tried the following and it printed "a" again:
a=a;[[ $a == "a" ]] && echo $a
Now I introduced an error by using arithmetic comparison:
a=abc;[ $a -eq "abc" ] && echo $a
I got an error message that makes sense:
-bash: [: abc: integer expression expected
Then I tried to do this with double bracket and got no error, but "abc":
a=abc;[[ $a -eq "abc" ]] && echo $a
I can sort of explain it (bash is trying to be accomodating), but then I got something that puzzles me. If I do that, I get an error message about recursion:
a=a;[[ $a -eq "a" ]] && echo $a
-bash: [[: a: expression recursion level exceeded (error token is "a")
If I use single brackets, there is no recursion but a reasonable error "integer expression expected":
a=a;[ $a -eq "a" ] && echo $a
-bash: [: abc: integer expression expected
This is weird. What Bash is trying to do in that "recursion" case with double brackets? I am talking about:
a=a;[[ $a -eq "a" ]] && echo $a
-bash: [[: a: expression recursion level exceeded (error token is "a")

It's trying to coerce a into a numeric form. It does this by treating its contents as a variable name to dereference; when the result of this is a loop, you get a "recursion level exceeded" error.
Thus:
a=b
b=10
[[ $a -eq 10 ]]
...is true.

Related

bash error when comparing string with slash

Why is it an error if string starts with a slash?
[[ "/a" -eq "a" ]]
-bash: [[: /a: syntax error: operand expected (error token is "/a")
Seems a bit unexpected.
Problem is not / but use of -eq operator, which is used for integer equality in shell.
If you change -eq with = then error will not be there:
[[ "/a" = "a" ]] && date || pwd

Regex Comparison in Shell Script

In Xcode 8 I have a Run Script that is comparing a string to a regex:
if [ "$MOBILE_BUNDLE_IDENTIFIER" =~ ".+(Debug)" ]
then
RESOURCE_PATH=${SRCROOT}/Resources/Clients/Cnt/Files/Debug
elif [ "$MOBILE_BUNDLE_IDENTIFIER" =~ ".+(Test)" ]
then
RESOURCE_PATH=${SRCROOT}/Resources/Clients/Cnt/Files/Production
elif [ "$MOBILE_BUNDLE_IDENTIFIER" =~ ".+(ProductionTest)" ]
then
RESOURCE_PATH=${SRCROOT}/Resources/Clients/Cnt/Files/Test
else
RESOURCE_PATH=${SRCROOT}/Resources/Clients/Cnt/Files/Store
fi
The variable $MOBILE_BUNDLE_IDENTIFIER will be one of the following:
com.cnt.Filer
com.cnt.Filer.ProductionTest
com.cnt.Filer.Debug
com.cnt.Filer.Test
When I run this I get the following error:
line 4: [: =~: binary operator expected
line 7: [: =~: binary operator expected
line 10: [: =~: binary operator expected
In the full script lines 4, 7 and 10 are the then statements.
Does anyone know how I can successfully compare my variable to the regex?
You should be using [[ string =~ regex ]] for regex in BASH
Don't quote regex
Looks like you don't even need regex, you can just do string comparison using ==
Your script can be this:
if [[ $MOBILE_BUNDLE_IDENTIFIER == *Debug* ]]; then
RESOURCE_PATH=${SRCROOT}/Resources/Clients/Cnt/Files/Debug
elif [[ $MOBILE_BUNDLE_IDENTIFIER == *Test* ]]; then
RESOURCE_PATH=${SRCROOT}/Resources/Clients/Cnt/Files/Production
elif [[ $MOBILE_BUNDLE_IDENTIFIER == *ProductionTest* ]]; then
RESOURCE_PATH=${SRCROOT}/Resources/Clients/Cnt/Files/Test
else
RESOURCE_PATH=${SRCROOT}/Resources/Clients/Cnt/Files/Store
fi
PS: You may also consider using case
case "$MOBILE_BUNDLE_IDENTIFIER" in
*Debug*)
RESOURCE_PATH=${SRCROOT}/Resources/Clients/Cnt/Files/Debug
;;
*Test*)
RESOURCE_PATH=${SRCROOT}/Resources/Clients/Cnt/Files/Production
;;
*ProductionTest*)
RESOURCE_PATH=${SRCROOT}/Resources/Clients/Cnt/Files/Test
;;
*)
RESOURCE_PATH=${SRCROOT}/Resources/Clients/Cnt/Files/Store
;;
esac

An error with if statement in shell scripting

I'm trying to write a shell script, but it's giving me a syntax error at the following command:
if [[ -n ${array[$x1]} -a [ expr length "$x1" -gt 2 ] ]]
This is the error message:
./project: line 45: syntax error in conditional expression
./project: line 45: syntax error near `-a'
./project: line 45: ` if [[ -n ${array[$x1]} -a [ expr length "$x1" -gt 2 ] ]]'
What am I doing wrong?
Use && not -a in [[ ]]
Also, expr length won't do what you expect here. The better approach, since you're already using bash extensions, is to use the ${#param} expansion to get the length of $param, and evaluate that within a math context, like so:
if [[ -n ${array[$x1]} ]] && (( ${#x1} > 2 )); then
...
fi

Comparing strings in bash script

./build_binaries.sh: line 43: [: ==: unary operator expected
I have this line (line 43) in my bash script which looks correct to me, but it keeps throwing error.
if [ ${platform} == "macosx" ]; then
Error:
./foo.sh: line 43: [: ==: unary operator expected
This is on OSX.
The problem is that $platform is an empty string. The usual workaround is to put it in quotes:
if [ "${platform}" == "macosx" ]
Example:
$ unset x
$ [ $x == 3 ]
-bash: [: ==: unary operator expected
$ [ "$x" == "3" ]
$
One possibility is to use a single =. That's the classic notation. Some shells allow ==, but others do not.
Also, you should enclose the ${platform} in double quotes; I think that it is an empty string, and this is confusing things.
platform=
if [ $platform == mac ]; then echo hi; else echo lo; fi
if [ "$platform" == mac ]; then echo hi; else echo lo; fi
This produces the error you're seeing on the second line.

How do you compare a string containing an angle bracket '<' in bash?

The following bash script is giving me problems:
#!/bin/bash
if [[ $VAR -eq "<EMPTY>" ]]; then echo "Hello World!"; fi
Bash fails, complaining:
line 3: [[: <EMPTY>: syntax error: operand expected (error token is "<EMPTY>")
How can I test if the string contained in VAR is equivalent to the string "<EMPTY>"?
You are using the wrong operator. == is for strings, -eq is for numbers.
#!/bin/bash
if [[ $VAR == "<EMPTY>" ]]; then echo "Hello World!"; fi
Inside [[ ... ]], -eq has a different meaning: it is used to compare integers. You can use (( ... )) to compare integeres with normal operators, though. Use the following for strings:
[[ $VAR == "<EMPTY>" ]]

Resources