Why equal to operator does not work if it is surrounded by space?
Solution 1
test
(or [ expr ]
) is a builtin function. Like all functions in bash, you pass it's arguments as whitespace separated words.
As the man page for bash builtins states: "Each operator and operand must be a separate argument."
It's just the way bash and most other Unix shells work.
Variable assignment is different.
In bash a variable assignment has the syntax: name=[value]
. You cannot put unquoted spaces around the =
because bash would not interpret this as the assignment you intend. bash treats most lists of words as a command with parameters.
E.g.
# call the command or function 'abc' with '=def' as argument
abc =def
# call 'def' with the variable 'abc' set to the empty string
abc= def
# call 'ghi' with 'abc' set to 'def'
abc=def ghi
# set 'abc' to 'def ghi'
abc="def ghi"
Solution 2
When the shell reads
if [ "$var1" = "$var2" ]
it invokes the command [ with 4 arguments. Whether [ is a builtin or an external command is irrelevant, but it may help to understand that it may be the external command /bin/[. The second argument is the literal '=' and the fourth is ']'. However, when the shell reads
if [ "$var1"= "$var2" ]
[ only gets 3 arguments: the expansion of $var1 with '=' appended, the expansion of $var2, and ']'. When it gets only 3 arguments, it expects the last argument to be ']' and the first argument to be a unary operator.
Solution 3
To add to the existing explanation, "$var1"="$var2"
is just a single non-empty string, and thus always evaluates as true in a conditional.
[ "$var1"="$var2" ] && echo true
The above command will always print out true
(even if var1
and var2
be empty).
Related videos on Youtube
Andrew-Dufresne
Call me Talha. I go by “talha131” at Github, DEV, and GoodReads. Email is the best way to reach me. I work on Jump Desktop. It is a remote desktop application for iOS, Android, macOS, and Windows. I play a broad role there; which includes research, product design, engineering, and deployment. I also lend a hand in user support. I have been working in the field for more than a decade. I do not pigeonhole myself to specific languages or frameworks. Through the years, I have learned and worked in several programming languages and frameworks. I have built apps for macOS, Windows, Linux, iOS, and Android. I am comfortable working in C, C++, Objective-C, C#, Python, and Java. I took up web development since early 2016 and picked up Go and NodeJS. I have built and delivered apps using ReactJS, Mobx, Redux, and ElectronJS. Besides the day job, I contribute to open source projects, beta test startup products, and offer consultancy. I work on my physical fitness and read books regularly; to be a stronger and better version of myself!
Updated on March 24, 2022Comments
-
Andrew-Dufresne about 2 years
I tried the following script
#!/bin/bash var1="Test 1" var2="Test 2" if [ "$var1"="$var2" ] then echo "Equal" else echo "Not equal" fi
It gave me
Equal
. Although it should have printedNot equal
Only when I inserted space around
=
it worked as intendedif [ "$var1" = "$var2" ]
and printed
Not equal
Why is it so? Why
"$var1"="$var2"
is not same as"$var1" = "$var2"
?Moreover, when I wrote
if [ "$var1"= "$var2" ]
, it gaveline 4: [: Test 1=: unary operator expected
What does it it mean? How come its expecting unary operator?
-
Andrew-Dufresne about 13 yearsThanks Charles Bailey. There is one thing more, as man page says "each operator and ...." then why
var = "test" ;
does not work? To make it work, I have to remove spacesvar="test";
Is assignment=
is not an operator? -
CB Bailey about 13 yearsThat man page applies to the
test
builtin function. In bash a variable assignment is part of the shell grammar, it's not a function. It requires no spaces. -
William Pursell about 13 years...and 'abc = def' invokes the command abc with two arguments '=' and 'def'
-
tripleee over 8 yearsBash
[[
is governed by the same shell syntax as all other constructs. Switching to[[
would not solve the OP's problem. As to whether this is "better" depends on whether you prioritize convenience over portability. If you are committed to Bash-only, it's probably true. -
knesenko over 8 yearsAs I wrote, I meant bash. Of course if you want your code to be portable, you should use /bin/sh
-
tripleee over 8 yearsStill, this does not attempt to address the OP's question, and should be posted as a comment instead (if at all).
-
linuxfan says Reinstate Monica about 2 years@knesenko you should read better both questions and comments...