Ao cancelar a referência de uma variável bash
, você deve usar $
sign. No entanto, parece que o seguinte está funcionando bem:
x=5
[[ x -gt 2 ]]
Alguém pode explicar isso?
Editar: (mais informações)
O que quero dizer é como e por que o comando [[]] está desreferenciando minha variável x sem o sinal $. E sim, se x = 1, a declaração é avaliada como falsa (status de retorno 1)
bash
bash-expansion
Hóspede
fonte
fonte
x=1
seguido por[[ x -gt 2]]
?Respostas:
A razão é que as
-eq
forças fazem uma avaliação aritmética dos argumentos.Um operador aritmético:
-eq
,-gt
,-lt
,-ge
,-le
e-ne
dentro de um[[ ]]
(em ksh, zsh e bash) meios para expandir automaticamente nomes de variáveis como na linguagem C, não precisa de um líder$
.Para confirmação, precisamos examinar o código-fonte do bash. O manual não oferece confirmação direta .
Dentro
test.c
do processamento de operadores aritméticos se enquadram nesta função:Onde
s
et
são ambos operandos. Os operandos são entregues a esta função:A função
evalexp
é definida dentroexpr.c
, que possui este cabeçalho:Portanto, sim, os dois lados de um operador aritmético caem (diretamente) na avaliação da expressão aritmética. Diretamente, sem buts, sem ifs.
Na prática, com:
Ambos falham:
O que está correto,
x
não está sendo expandido ex
não é igual a um número.Contudo:
A variável denominada
x
é expandida (mesmo sem um $).Isso não acontece
[…]
no a zsh ou no bash (no ksh).É o mesmo que acontece dentro de um
$((…))
:E, por favor, entenda que isso é (muito) recursivo (exceto em hífen):
A 😮
E bastante arriscado:
O erro de sintaxe pode ser facilmente evitado:
Como diz o ditado: higienize sua entrada
fim de 😮
O externo (mais antigo)
/usr/bin/test
(não o internotest
) e o ainda mais antigo e também o externoexpr
não expandem expressões apenas números inteiros (e, aparentemente, apenas números inteiros decimais):fonte
[[
uma palavra-chave, operadores e operandos são detectados quando o comando é lido e não após a expansão. Assim,[[
pode tratar-eq
de uma maneira mais inteligente do que, digamos[
,. Mas o que me pergunto é: onde podemos encontrar documentação sobre o bash lógico usado para interpretar comandos compostos? Não parece muito óbvio para mim e, aparentemente, não consigo encontrar explicações satisfatórias emman
ouinfo bash
.test
secção de homem zshbuiltins operadores aritméticos esperar inteiro argumentos em vez de expressões aritméticas . O que confirma que alguns argumentos são tratados como expressões aritméticas pelo teste incorporado sob condições não especificadas nesta citação. Eu vou confirmar com o código fonte .... ...Os operandos das comparações numéricas
-eq
,-gt
,-lt
,-ge
,-le
e-ne
são tomados como expressões aritméticas. Com algumas limitações, eles ainda precisam ser palavras de casca simples.O comportamento dos nomes de variáveis na expressão aritmética é descrito em Aritmética do Shell :
e também:
Mas não consigo encontrar a parte da documentação em que se diz que as comparações numéricas usam expressões aritméticas. Não é descrito em Construções condicionais em
[[
, nem em Expressões condicionais de bash .Mas, por experimento, parece funcionar como dito acima.
Então, coisas assim funcionam:
isso também (o valor da variável é avaliado):
Mas isso não acontece; não é uma única palavra de shell quando a
[[ .. ]]
análise é analisada; portanto, há um erro de sintaxe na condicional:Em outros contextos aritméticos, não há necessidade de a expressão ficar sem espaço em branco. Isso é impresso
999
, pois os colchetes delimitam inequivocamente a expressão aritmética no índice:Por outro lado, a
=
comparação é uma correspondência de padrões e não envolve aritmética, nem a expansão automática de variáveis feita em um contexto aritmético (Construções Condicionais):Portanto, isso é falso, pois as strings são obviamente diferentes:
como é isso, mesmo que os valores numéricos sejam os mesmos:
e aqui também as comparações (
x
e6
) são diferentes:Isso expandiria a variável, no entanto, então isso é verdade:
fonte
arg1 OP arg2
diz que os argumentos podem ser números inteiros positivos ou negativos, o que suponho que implica que eles sejam tratados como expressões aritméticas. Confusamente, isso também implica que eles não podem ser zero. :)[
e não existem expressões aritméticas. Em vez disso, o Bash reclama de não-números inteiros.[
é um comando externo, não tem acesso a variáveis de shell. Muitas vezes, é otimizado com um comando interno, mas ainda se comporta da mesma maneira.[
apenas como[[
. Mesmo com[
, os operandos-eq
e amigos são / precisam ser inteiros, de modo que a descrição também se aplica. Tomando "deve ser um número inteiro" para significar "são interpretados como expressões aritméticas" não se aplica nos dois casos. (Provavelmente, pelo menos em parte devido a[
agir como um comando comum, como você diz.)Sim, sua observação está correta, a expansão de variáveis é realizada em expressões entre colchetes duplos
[[ ]]
, para que você não precise colocar$
na frente de um nome de variável.Isso é explicitamente declarado no
bash
manual:Observe que este não é o caso da versão de colchete único
[ ]
, pois[
não é uma palavra-chave do shell (sintaxe), mas sim um comando (no bash está embutido, outros shells podem usar externo, alinhado para testar).fonte
(x=1; [[ $x = 1 ]]; echo $?)
retornos0
,(x=1; [[ x = 1 ]]; echo $?)
retornos1
, ou seja, a expansão dos parâmetros não é executadax
quando comparamos as strings. Esse comportamento parece uma avaliação aritmética desencadeada por expansão aritmética, ou seja, o que acontece em(x=1; echo $((x+1)))
. (Sobre a avaliação aritmética,man bash
afirma que "dentro de uma expressão, variáveis do shell também podem ser referenciados pelo nome sem usar a expansão de parâmetros de sintaxe).-gt
operador espera um número, então toda a expressão é reavaliada como se estivesse dentro(())
, por outro lado,==
espera seqüências de caracteres para que a função de correspondência de padrões seja acionada. Eu não procurei no código fonte, mas parece razoável.[
é um shell embutido no bash.