La página man de GNU bash para [[..]] explica que el operador ejecuta una expresión condicional y
Devuelve un estado de 0 o 1 dependiendo de la evaluación de la expresión condicional expression . Las expresiones se componen de las primarias que se describen a continuación en Expresiones condicionales de Bash.
Pero el operador aritmético es no parte de las expresiones condicionales admitidas (primaries ) dentro de [[..]] lo que significa que la expresión se ve obligada a ejecutarse como una comparación de cadenas, es decir,
(( $n < 3))
no se ejecuta en contexto aritmético pero tan simple comparación lexicográfica (cadena) como
[[ 100 < 3 ]]
que siempre resultará verdadero, porque los valores ASCII para 1 , 0 , 0 aparecer antes de 3
Pero dentro [[..]] las operaciones aritméticas son compatibles si usa -lt , -gt
arg1 OP arg2
OP es uno de -eq , -ne , -lt , -le , -gt , o -ge . Estos operadores binarios aritméticos devuelven verdadero si arg1 es igual a, no igual a, menor que, menor que o igual a, mayor que, o mayor que o igual a arg2 , respectivamente.
Así que habías escrito tu expresión como
a=start; n=100; [[ " stop start status " =~ " $a " && $n -lt 3 ]] && echo ok || echo bad
bad
habría funcionado como se esperaba.
O incluso si hubiera forzado el uso de expresiones aritméticas al anteponer $ antes de ((..)) y lo escribió como se muestra a continuación (tenga en cuenta que bash no tiene un comportamiento documentado para $((..)) dentro de [[..]] ). El comportamiento esperado probable es que la expresión aritmética se expanda antes del [[..]] se evalúa y la salida resultante se evalúa en un contexto de cadena como [[ 0 ]] lo que significa una cadena no vacía.
a=start; n=5; [[ " stop start status " =~ " $a " && $(( $n < 3 )) ]] && echo ok || echo bad
El resultado aún se vería mal, porque la expresión aritmética dentro de [[..]] se descompone en una expresión de comparación de cadena unaria no vacía como
$(( 5 < 3 ))
0
[[ -n 0 ]]
El resultado de la evaluación aritmética 0 (falso) es tomado como una entidad distinta de cero por el operador de prueba y afirma verdadero en el lado derecho de && . Lo mismo se aplicaría para el otro caso, p. di n=1
$(( 1 < 3 ))
1
[[ -n 1 ]]
En pocas palabras, use los operandos correctos para la operación aritmética dentro de [[..]] .
(( es una "palabra clave" que introduce el enunciado aritmético. Dentro de [[ , sin embargo, no puede usar otras declaraciones. Tu puedes Sin embargo, use paréntesis para agrupar expresiones, eso es lo que (( ... )) es:un "grupo doble" redundante. Los siguientes son todos equivalentes, debido a las precedencias de < y && :
[[ " stop start status " =~ " $2 " && (($#<3)) ]][[ " stop start status " =~ " $2 " && ($#<3) ]][[ " stop start status " =~ " $2 " && $#<3 ]]
Si desea una comparación de enteros, use -lt en lugar de < , pero tampoco es necesario que quepa todo dentro de [[ ... ]] . Puede usar una declaración condicional y una declaración aritmética juntas en una lista de comandos.
{ [[ " stop start status " =~ " $2 " ]] && (($#<3)) ; } || { echo "Usage $0 file_name command"; exit 1;}
En este caso, ... && ... || ... funcionará de la manera esperada, aunque en general ese no es el caso. Prefiero un if declaración en su lugar.
if [[ " stop start status " =~ " $2 " ]] && (($#<3)); then
echo "Usage $0 file_name command"
exit 1
fi