Lo que has escrito en realidad casi funciona (funcionaría si todas las variables fueran números), pero no es una forma idiomática en absoluto.
(…)
los paréntesis indican una subshell . Lo que hay dentro de ellos no es una expresión como en muchos otros idiomas. Es una lista de comandos (al igual que los paréntesis externos). Estos comandos se ejecutan en un subproceso separado, por lo que cualquier redirección, asignación, etc. realizada dentro de los paréntesis no tiene efecto fuera de los paréntesis.
- Con un signo de dólar inicial,
$(…)
es una sustitución de comando : hay un comando dentro de los paréntesis, y la salida del comando se usa como parte de la línea de comando (después de expansiones adicionales a menos que la sustitución sea entre comillas dobles, pero esa es otra historia ) .
{ … }
Las llaves son como paréntesis en el sentido de que agrupan comandos, pero solo influyen en el análisis, no en la agrupación. El programa x=2; { x=4; }; echo $x
imprime 4, mientras que x=2; (x=4); echo $x
imprime 2. (También las llaves requieren espacios a su alrededor y un punto y coma antes del cierre, mientras que los paréntesis no. Eso es solo una peculiaridad de sintaxis).
- Con un signo de dólar principal,
${VAR}
es una expansión de parámetros , que se expande al valor de una variable, con posibles transformaciones adicionales.
((…))
los paréntesis dobles rodean una instrucción aritmética , es decir, un cálculo en enteros, con una sintaxis similar a otros lenguajes de programación. Esta sintaxis se usa principalmente para asignaciones y en condicionales.
- La misma sintaxis se usa en expresiones aritméticas
$((…))
, que se expanden al valor entero de la expresión.
[[ … ]]
los corchetes dobles rodean las expresiones condicionales . Las expresiones condicionales se basan principalmente en operadores como -n $variable
para probar si una variable está vacía y -e $file
para probar si existe un archivo. También hay operadores de igualdad de cadenas: "$string1" == "$string2"
(tenga en cuenta que el lado derecho es un patrón, por ejemplo, [[ $foo == a* ]]
prueba si $foo
comienza con a
mientras que las [[ $foo == "a*" ]]
pruebas $foo
son exactas a*
), y lo familiar !
, &&
y ||
operadores para negación, conjunción y disyunción, así como paréntesis para la agrupación. Tenga en cuenta que necesita un espacio alrededor de cada operador (por ejemplo [[ "$x" == "$y" ]]
, no [[ "$x"=="$y" ]]
), y un espacio o un carácter como ;
dentro y fuera de los corchetes (por ejemplo [[ -n $foo ]]
, no[[-n $foo]]
)
[ … ]
los corchetes simples son una forma alternativa de expresiones condicionales con más peculiaridades (pero más antiguas y portátiles). No escribas ninguno por ahora; empiece a preocuparse por ellos cuando encuentre scripts que los contengan.
Esta es la forma idiomática de escribir su prueba en bash:
if [[ $varA == 1 && ($varB == "t1" || $varC == "t2") ]]; then
Si necesita portabilidad a otros shells, este sería el camino (tenga en cuenta las citas adicionales y los conjuntos de corchetes separados alrededor de cada prueba individual, y el uso del =
operador tradicional en lugar de la ==
variante ksh / bash / zsh ):
if [ "$varA" = 1 ] && { [ "$varB" = "t1" ] || [ "$varC" = "t2" ]; }; then
Gilles 'SO- deja de ser malvado'
fuente
==
para diferenciar la comparación de la asignación de una variable (que también es=
)[[ $varA = 1 && ($varB = "t1" || $varC = "t2") ]]
no inician un subproceso, aunque el primer punto dice explícitamente: "Lo que está dentro [paréntesis] no es una expresión como en muchos otros idiomas", ¡pero ciertamente está aquí! Eso es probablemente obvio para el experto en bash wiz, pero ni siquiera para mí, de inmediato. La confusión puede surgir porque los paréntesis simples se pueden usar en unaif
declaración, pero no en expresiones dentro de corchetes dobles.==
no es realmente "más idiomático" que=
. Tienen el mismo significado, pero==
es una variante ksh también disponible en bash y zsh, mientras que=
es portátil. Realmente no hay ninguna ventaja de usar==
, y no funciona en sh simple.==
adentro[[ … ]]
, si lo desea, pero=
tiene la ventaja de trabajar también[ … ]
, por lo que le recomiendo no acostumbrarse a usarlo==
.muy cerca
Deberia trabajar.
descomponiéndolo
es una comparación entera donde como
Es una comparación de cadenas. de lo contrario, solo estoy agrupando las comparaciones correctamente.
Los corchetes dobles delimitan una expresión condicional. Y, creo que lo siguiente es una buena lectura sobre el tema: "(IBM) Prueba de desmitificación, [, [[, ((, y si-entonces-otro"
fuente
't1'
es innecesaria, ¿verdad? Porque a diferencia de las instrucciones aritméticas en paréntesis dobles, dondet1
sería una variable,t1
en una expresión condicional entre corchetes dobles es solo una cadena literal. Es decir,[[ $varB == 't1' ]]
es exactamente lo mismo que[[ $varB == t1 ]]
, ¿verdad?Una versión muy portátil (incluso para legacy bourne shell):
Esto tiene la calidad adicional de ejecutar solo un subproceso como máximo (que es el proceso
[
), sea cual sea el sabor del shell.Reemplace
=
con-eq
si las variables contienen valores numéricos, por ej.3 -eq 03
es cierto, pero3 = 03
Es falso. (comparación de cadenas)fuente
Aquí está el código para la versión corta de la declaración if-then-else:
Presta atención a lo siguiente:
||
y&&
operandos dentro si la condición (es decir, entre paréntesis) son operandos lógicos (o / y)||
y&&
operandos afuera si la condición significa entonces / elsePrácticamente la declaración dice:
if (a = 1 o b = 2) entonces "ok" más "nok"
fuente
( ... )
crea una subshell. Es posible que desee utilizar llaves en su{ ... }
lugar. Cualquier estado creado en una subshell no será visible en la persona que llama.fuente