Por que igual ao operador não funciona se não estiver rodeado por espaço?

Eu tentei o seguinte script

#!/bin/bash var1="Test 1" var2="Test 2" if [ "$var1"="$var2" ] then echo "Equal" else echo "Not equal" fi 

Isso me deu Equal . Embora devesse ter impresso Not equal

Somente quando eu inseri espaço ao redor = funcionou como pretendido

 if [ "$var1" = "$var2" ] 

e impresso Not equal

Por que é tão? Por que "$var1"="$var2" não é o mesmo que "$var1" = "$var2" ?

Além disso, quando eu escrevi if [ "$var1"= "$var2" ] , ele dava

 line 4: [: Test 1=: unary operator expected 

O que isso significa? Como é que espera o seu operador unário?

   

test (ou [ expr ] ) é uma function interna. Como todas as funções no bash, você passa seus argumentos como espaços em branco separados por palavras.

Como diz a página man do bash builtins: “Cada operador e operando deve ser um argumento separado”.

É apenas o modo como o bash e a maioria dos outros shells Unix funcionam.

Atribuição variável é diferente.

No bash, uma atribuição de variável tem a syntax: name=[value] . Você não pode colocar espaços sem aspas em torno de = porque o bash não interpretaria isso como a designação que você pretende. O bash trata a maioria das listas de palavras como um comando com parâmetros.

Por exemplo

 # 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" 

Quando a casca lê

 if ["$ var1" = "$ var2"]

ele invoca o comando [com 4 argumentos. Se [é um comando interno ou externo é irrelevante, mas pode ajudar a entender que pode ser o comando externo / bin / [. O segundo argumento é o literal ‘=’ e o quarto é ‘]’. No entanto, quando o shell lê

 if ["$ var1" = "$ var2"]

[somente recebe 3 argumentos: a expansão de $ var1 com ‘=’ anexada, a expansão de $ var2 e ‘]’. Quando recebe apenas 3 argumentos, espera que o último argumento seja ‘]’ e o primeiro argumento seja um operador unário.

Para adicionar à explicação existente, "$var1"="$var2" é apenas uma única string não vazia e, portanto, sempre é avaliada como verdadeira em uma condicional.

 [ "$var1"="$var2" ] && echo true 

O comando acima sempre imprime true (mesmo que var1 e var2 estejam vazios).

No bash o melhor é usar [[]]:

 x="test" y="test" if [[ "${x}" = "${y}" ]]; then echo "Equals" else echo "No equals" fi