GNU/Linux >> Tutoriales Linux >  >> Linux

¿Por qué Bash `(())` no funciona dentro de `[[]]`?

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

Linux
  1. ¿Por qué no funciona ~/.bash_profile?

  2. ¿Por qué la sustitución del proceso Bash no funciona con algunos comandos?

  3. ¿Por qué Lsdel en Debugfs no funciona?

  4. ¿Por qué no puedo usar Cd en un script Bash?

  5. ¿Por qué el nombre de host --fqdn no funciona en mi computadora con Ubuntu?

CentOS 8 VM no funciona en VirtualBox 5.2 en Ubuntu 18.04

¿Por qué no funciona mi enlace simbólico?

¿Por qué no sale un ciclo bash while cuando se conecta a un subcomando terminado?

¿Por qué el puente de Linux no funciona?

¿Por qué borrar el historial de bash no es suficiente?

¿Por qué a gdb no le gustan los alias?