Por que '==' se comporta de maneira diferente dentro de '[…]' em zsh e bash?

7

Eu recebo o que esperava ao fazer isso em bash :

[ "a" == "a" ] && echo yes

Ele me deu yes .

Mas quando faço isso em zsh , recebo o seguinte:

zsh: = not found

Por que o mesmo comando ( /usr/bin/[ ) se comporta de maneira diferente em shells diferentes?

    
por Johnson Steward 15.01.2016 / 09:44

4 respostas

18

Não é /usr/bin/[ em nenhum dos shells. No Bash, você está usando o comando test / [ incorporado e similarmente em zsh .

A diferença é que zsh também tem uma expansão = : =foo se expande para o caminho para o executável foo . Isso significa que == é tratado como tentativa de localizar um comando chamado = em seu PATH . Como esse comando não existe, você recebe o erro

zsh: = not found

que você viu (e, de fato, a mesma coisa aconteceria mesmo se você realmente estivesse usando /usr/bin/[ ).

Você pode usar == aqui, se você realmente quiser. Isso funciona como você esperava no zsh:

[ "a" "==" "a" ] && echo yes

porque a cotação impede a execução de =word em execução. Você também pode desativar a opção equals com setopt noequals .

No entanto, você estaria melhor:

  • Usando o único = , o teste de igualdade compatível com POSIX ; ou
  • Melhor ainda, usando os condicionais [[ com == em ambos Bash e zsh . Em geral, [[ é apenas melhor e mais seguro, incluindo evitar esse tipo de problema (e outros) com regras especiais de análise dentro.
por 15.01.2016 / 10:00
2

[ é um comando interno do shell no bash e no zsh:

$ type [
[ is a shell builtin

Na documentação Comandos internos do Shell a>:

Builtin commands are contained within the shell itself. When the name of a builtin command is used as the first word of a simple command (see Simple Commands), the shell executes the command directly, without invoking another program. Builtin commands are necessary to implement functionality impossible or inconvenient to obtain with separate utilities.

A documentação oficial ( $ help test ) só permite usar = :

STRING1 = STRING2

True if the strings are equal.

Então, a expressão correta seria:

$ [ "a" = "a" ] && echo yes
yes

O que acontece é que o bash é um pouco menos rigoroso. Suportando o operador == com [ parece seja uma extensão bash e não é recomendado usá-la:

string1 == string2

string1 = string2

True if the strings are equal. When used with the [[ command, this performs pattern matching as described above (see Conditional Constructs).

‘=’ should be used with the test command for POSIX conformance.

Se você quiser usar == , use a palavra-chave [[ :

$ [[ "a" == "a" ]] && echo yes
yes

Tenha em mente que [[ é menos portável (não é POSIX). Mas tanto bash quanto zsh suportam isso.

    
por 15.01.2016 / 10:11
2

E zsh e bash dão a mesma resposta ( type também é incorporado para ambos os shells):

$ type -a [
[ is a shell builtin
[ is /usr/bin/[
    
por 15.01.2016 / 09:54
1

Em ambos os shells, bash e zsh , o utilitário [ é um shell embutido. Esta é a implementação de shells dessa ferramenta, ela é usada de preferência para o binário /usr/bin/[ . Os diferentes resultados encontrados são causados por diferentes implementações.

Em bash , o utilitário [ aceita CONDITIONAL EXPRESSIONS como o comando [[ compound. De acordo com a página de manual bashs, tanto = como == são válidos:

string1 == string2
string1 = string2
        True if the strings are equal.  = should be used with the test command for POSIX
        conformance.

Em zsh , o utilitário [ tenta implementar o POSIX e suas extensões onde elas são especificadas. Na especificação do utilitário de teste POSIX , não há nenhum operador == definido.

    
por 15.01.2016 / 10:05

Tags