Comparing strings in bash script - bash

./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.

Related

Unexpected operator in if statement

In the following two lines I get this error?
What is wrong?
Debian Buster
my.sh: 101: [: !=: unexpected operator
my.sh: 103: [: !=: unexpected operator
if [ $CONTINUE != "y" ] && [ "$CONTINUE" != "n" ]; then
elif [ $CONTINUE = "n" ]; then
update
echo "\nContinue downloading? [y/n]"
read CONTINUE
# Error: Invalid argument
if [ $CONTINUE != "y" ] && [ $CONTINUE != "n" ]; then
error "Invalid argument"
elif [ $CONTINUE = "n" ]; then
echo "\nDonwload terminated!"
exit
fi
The script you’ve posted has various issues, which are highlighted by ShellCheck:
Line 1:
echo "\nContinue downloading? [y/n]"
^-- SC2028: echo may not expand escape sequences. Use printf.
Line 2:
read CONTINUE
^-- SC2162: read without -r will mangle backslashes.
Line 5:
if [ $CONTINUE != "y" ] && [ $CONTINUE != "n" ]; then
^-- SC2086: Double quote to prevent globbing and word splitting.
^-- SC2086: Double quote to prevent globbing and word splitting.
Did you mean: (apply this, apply all SC2086)
if [ "$CONTINUE" != "y" ] && [ "$CONTINUE" != "n" ]; then
Line 7:
elif [ $CONTINUE = "n" ]; then
^-- SC2086: Double quote to prevent globbing and word splitting.
Did you mean: (apply this, apply all SC2086)
elif [ "$CONTINUE" = "n" ]; then
Line 8:
echo "\nDonwload terminated!"
^-- SC2028: echo may not expand escape sequences. Use printf.
But despite these issues the script actually otherwise works as expected on Debian (Buster)’s default shell (which is dash). You might be running a non-default shell. The easiest way to solve your issue is therefore to
Declare a valid shebang line
Fix the issues highlighted above.
Which leaves us with this:
#!/bin/sh
printf "\nContinue downloading? [y/n] "
read -r CONTINUE
error() {
printf >&2 '%s\n' "$#"
exit 1
}
if [ "$CONTINUE" != y ] && [ "$CONTINUE" != n ]; then
error "Invalid argument"
elif [ "$CONTINUE" = n ]; then
printf "\nDownload terminated!\n"
exit
fi
(This also adds a definition for the undefined error call; substitute as appropriate.)

Bash does into unexpected recursion when processing expression inside [[

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.

How to use comparison in bash

I'm trying to use comparison in bash, but just can't make it work.
#!/bin/bash
str="75.00 W, 170.00 W"
function str_check {
pow_array=()
regexp='([0-9]+)\.[0-9]+[[:space:]]W,[[:space:]]([0-9]+)\.[0-9]+[[:space:]]W'
[[ $str =~ $regexp ]] && for (( i = 0; i < 3; i++ )); do
pow_array+=("${BASH_REMATCH[$i]}")
done
if [ "$1" -lt ${pow_arr[1]} ]; then
echo "Available power limit is ${pow_array[0]}"
echo "Setting up ${pow_array[1]}"
elif [ "$1" -gt "${pow_arr[2]}" ]; then
echo "Available power limit is ${pow_array[0]}"
echo "Setting up ${pow_array[2]}"
else
echo "All good, setting up $1"
fi
}
str_check "70"
str_check "100"
str_check "200"
Already have tried '[[', '((' '[', qoute and unquote everething, but getting all kind of errors or wrong results. Need someone to give me a hand.
./t.sh: line 9: [: 70: unary operator expected
./t.sh: line 12: [: : integer expression expected
Time to discover shellcheck !
Line 9:
if [ "$1" -lt ${pow_arr[1]} ]; then
^-- SC2154: pow_arr is referenced but not assigned (did you mean 'pow_array'?).
^-- SC2086: Double quote to prevent globbing and word splitting.
Change all the references to pow_arr into pow_array and it works !

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

Ubuntu shell script getting error

I am developing simple shell script which copy all my present directory files to backup directory which will be exist in present working directory. now i'm getting error when i pass more then one condition in if.
#!/bin/bash
filename=nx.pdf
for i in *;
do
echo $i;
if [ $i == backup || $i == $filename ] ; then
echo "Found backup."
else
echo "Part 2"
cp -rf $i backup
fi
done
I am getting error
asd.sh: line 6: [: missing `]'
asd.sh: line 6: ==: command not found
Part 2
deployee.sh
asd.sh: line 6: [: missing `]'
asd.sh: line 6: ==: command not found
Part 2
The compare operator is = (as defined in POSIX). But == works on some shells as well.
Something like this should work:
if [ $i = backup ] || [ $i = $filename ] ; then
You should quote $i in "". Otherwise you get syntax errors for filenames with blanks.
To be able to use || and && in conditions, you have to use the double square brackets:
if [[ $i == backup || $i == $filename ]] ; then

Resources