Achei algo surpreendente quando estou escrevendo para algum script bash hoje. Eu o fixei neste exemplo mínimo.
[[ a>b ]]; echo $?
Com base no meu entendimento, como não há espaços ao redor do >
, isso deve testar se a string a>b
não está vazia e deve retornar um código de erro de 0
. No entanto, o comando acima ecoa 1
em ambas as versões do bash que testei (detalhes abaixo).
Eu também testei usando o antigo test
comando "good",
[ a>b ]; echo $?
echos 0
(testa se a string a
não está vazia e cria um arquivo vazio b
no meu diretório de trabalho atual, aparentemente >b
é tratado como um redirecionamento, o que é compreensível).
Então eu tentei mais algumas outras coisas
[[ b>a ]]; echo $?
ecos0
e nenhum arquivo é criado.[[ b<a ]]; echo $?
ecos1
e nenhum arquivo é criado.[[ a<b ]]; echo $?
ecos0
e nenhum arquivo é criado.[ b>a ]; echo $?
echos0
e cria um arquivo vazioa
.[ b<a ]; echo $?
relata um erro de arquivo ausentea
e ecos1
devido a esse erro.[ a<b ]; echo $?
relata um erro de arquivo ausenteb
e ecos1
devido a esse erro.[[ a=b ]]; echo $?
echos0
porque está testando se a stringa=b
não está vazia como eu esperava.[ a=b ]; echo $?
ecos0
pelo mesmo motivo.[[ a==b ]]; echo $?
ecos0
pelo mesmo motivo.[ a==b ]; echo $?
ecos0
pelo mesmo motivo.[[ a!=a ]]; echo $?
e[ a!=a ]; echo $?
ambos ecoam0
(esperado)
Portanto, parece que apenas os espaços ao redor de <
e >
podem ser omitidos em uma expressão condicional, mas não =
ou ==
ou !=
se a intenção for fazer comparação de strings. Mas por que ele é projetado dessa maneira? Também pode ser minha omissão, mas isso não parece estar documentado em nenhum lugar do manual do bash.
Meu problema original é tentar usar >
sem escape como parte de um padrão em uma expressão condicional ( [[ ... ]]
). Originalmente, pensei que, desde que não envolvesse o >
com espaços, poderia usá-lo sem escape sem problemas, porque não faz sentido (e acaba sendo impossível após alguns testes) fazer redirecionamentos dentro de um condicional expressão também.
No entanto, verifica-se que não é o caso. É claro que a solução simples é apenas escapar disso >
e escrever \>
, mas não entendo por que isso é necessário.
Aqui estão as versões do bash que usei para testar,
GNU bash, version 5.2.2(1)-release (aarch64-unknown-linux-android)
e
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Meus experimentos são realizados sob env -i bash --norc --noprofile
.