Al desreferenciar una variable bash
, debe usar $
signo. Sin embargo, parece que lo siguiente está funcionando bien:
x=5
[[ x -gt 2 ]]
¿Alguien puede explicar esto?
Editar: (más información)
Lo que quiero decir es cómo y por qué el comando [[]] está desreferenciando mi variable x sin el signo $. Y sí, si x = 1, la declaración se evalúa como falsa (estado de retorno 1)
bash
bash-expansion
Invitado
fuente
fuente
x=1
sigue[[ x -gt 2]]
?Respuestas:
La razón es que
-eq
obliga a una evaluación aritmética de los argumentos.Un operador aritmético:
-eq
,-gt
,-lt
,-ge
,-le
y-ne
dentro de una[[ ]]
(en ksh, zsh y bash) medios para expandir automáticamente los nombres de variables como en el lenguaje C, no necesita de un líder$
.Para la confirmación debemos buscar en el código fuente de bash. El manual no ofrece confirmación directa .
Dentro
test.c
del procesamiento de operadores aritméticos entran en esta función:Donde
s
yt
son ambos operandos. Los operandos se entregan a esta función:La función
evalexp
se define dentroexpr.c
, que tiene este encabezado:Entonces, sí, ambos lados de un operador aritmético caen (directamente) en la evaluación de expresiones aritméticas. Directamente, sin peros, sin peros.
En la práctica, con:
Ambos fallan:
Lo cual es correcto,
x
no se está expandiendo yx
no es igual a un número.Sin embargo:
La variable nombrada
x
se expande (incluso sin un $).Esto no sucede para un
[…]
en zsh o bash (lo hace en ksh).Eso es lo mismo que sucede dentro de un
$((…))
:Y, por favor, comprenda que esto es (muy) recursivo (excepto en guión y guión):
A 😮
Y bastante arriesgado:
El error de sintaxis podría evitarse fácilmente:
Como dice el refrán: desinfecte su aporte
fin de 😮
Tanto el (más antiguo) externo
/usr/bin/test
(no el incorporadotest
) como el aún más antiguo y también externoexpr
no expanden las expresiones solo enteros (y aparentemente, solo enteros decimales):fuente
[[
una palabra clave, los operadores y los operandos se detectan cuando se lee el comando y no después de la expansión. De este modo[[
se puede tratar-eq
de una manera más inteligente que, por ejemplo,[
. Pero lo que me pregunto es: ¿dónde podemos encontrar documentación sobre la lógica que utiliza bash para interpretar comandos compuestos? No me parece muy obvio y aparentemente no puedo encontrar explicaciones satisfactorias enman
oinfo bash
.test
sección de los operadores aritméticos man zshbuiltins que esperan argumentos enteros en lugar de expresiones aritméticas . Lo que confirma que algunos argumentos son tratados como expresiones aritméticas por la prueba incorporada en condiciones no especificadas en esta cita. Voy a confirmo con el código fuente ... ....Los operandos de las comparaciones numéricas
-eq
,-gt
,-lt
,-ge
,-le
y-ne
se toman como expresiones aritméticas. Con alguna limitación, todavía necesitan ser palabras de shell único.El comportamiento de los nombres de variables en la expresión aritmética se describe en Shell Arithmetic :
y también:
Pero en realidad no puedo encontrar la parte de la documentación donde se dice que las comparaciones numéricas toman expresiones aritméticas. No se describe en Construcciones condicionales
[[
, ni se describe en Expresiones condicionales bash .Pero, por experimento, parece funcionar como se dijo anteriormente.
Entonces, cosas como esta funcionan:
esto también (se evalúa el valor de la variable):
Pero esto no; no es una sola palabra de shell cuando
[[ .. ]]
se analiza, por lo que hay un error de sintaxis en el condicional:En otros contextos aritméticos, no es necesario que la expresión no tenga espacios en blanco. Esto se imprime
999
, ya que los corchetes delimitan inequívocamente la expresión aritmética en el índice:Por otro lado, la
=
comparación es una coincidencia de patrones y no implica aritmética, ni la expansión automática de variables realizada en un contexto aritmético (Construcciones condicionales):Entonces esto es falso ya que las cadenas son obviamente diferentes:
como es esto, a pesar de que los valores numéricos son los mismos:
y aquí, también, las cadenas (
x
y6
) se comparan, son diferentes:Sin embargo, esto expandiría la variable, así que esto es cierto:
fuente
arg1 OP arg2
dice que los argumentos pueden ser enteros positivos o negativos, lo que supongo que implica que se tratan como expresiones aritméticas. Confusamente, también implica que no pueden ser cero. :)[
, y allí no son expresiones aritméticas. En cambio, Bash se queja de los no enteros.[
es un comando externo, no tiene acceso a variables de shell. A menudo se optimiza con un comando incorporado, pero aún se comporta igual.[
tanto como a[[
. Incluso con[
, los operandos-eq
y amigos son / tienen que ser enteros, por lo que esa descripción también se aplica. Tomar "debe ser enteros" para significar "se interpretan como expresiones aritméticas" no se aplica en ambos casos. (Probablemente, al menos en parte debido a[
que actúa como un comando normal, como usted dice.)Sí, su observación es correcta, la expansión de la variable se realiza en expresiones entre corchetes dobles
[[ ]]
, por lo que no necesita poner$
delante de un nombre de variable.Esto se establece explícitamente en el
bash
manual:Tenga en cuenta que este no es el caso de la versión de un solo parche
[ ]
, ya[
que no es una palabra clave de shell (sintaxis), sino más bien un comando (en bash está integrado, otros shells podrían usar externo, alineado para probar).fuente
(x=1; [[ $x = 1 ]]; echo $?)
retornos0
,(x=1; [[ x = 1 ]]; echo $?)
retornos1
, es decir, la expansión de parámetros no se realizax
cuando comparamos cadenas. Este comportamiento se parece a la evaluación aritmética desencadenada por la expansión aritmética, es decir, lo que sucede en(x=1; echo $((x+1)))
. (Acerca de la evaluación aritmética,man bash
establece que "Dentro de una expresión, las variables de shell también pueden ser referenciadas por nombre sin usar la sintaxis de expansión de parámetros).-gt
operador espera un número, la expresión completa se reevalúa como si estuviera dentro(())
, por otro lado,==
espera cadenas, por lo que se activa la función de coincidencia de patrones. No busqué en el código fuente, pero suena razonable.[
es un caparazón incorporado en bash.