Comparación de enteros: expresión aritmética o expresión condicional

En Bash, se pueden comparar dos enteros usando una expresión condicional

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, no igual, menor que, menor o igual que, mayor o mayor o igual que arg2 , respectivamente. Arg1 y arg2 pueden ser números enteros positivos o negativos.

o expresión aritmética:

<= >= < > comparación

== != igualdad y desigualdad

¿Por qué tenemos dos formas diferentes de comparar dos enteros? ¿Cuándo usar cuál?

Por ejemplo, [[ 3 -lt 2 ]] usa una expresión condicional y (( 3 < 2 )) usa una expresión aritmética. Ambos devuelven 0 cuando la comparación es verdadera

Al comparar dos números enteros, ¿estos dos métodos siempre se pueden usar indistintamente? Si es así, ¿por qué Bash tiene dos métodos en lugar de uno?

Comentarios

  • = != < <= > >= comparar cadenas . 1 -eq 01 pero 1 != 01 y 8 -lt 42 pero 8 > 42
  • Están sobrecargados en expresiones aritméticas.
  • usted ‘ tendrá que buscar en los registros de cambios de bash para averiguar cuándo se adicional. Sospecho que las expresiones aritméticas se agregaron mucho más tarde que el comando de prueba.
  • No estoy preguntando sobre la comparación de cadenas. @muru.

Respuesta

Sí, tenemos dos formas diferentes de comparar dos enteros.

Parece que estos hechos no son ampliamente aceptados en este foro:

  1. Dentro del idioma [ ] los operadores para la comparación aritmética son -eq, -ne, -lt, -le, -gt y -ge.

    Como también están dentro de un comando de prueba y dentro de un [[ ]].

    Sí, dentro de estos modismos, =, <, etc. operadores de cadena.

  2. Dentro del idioma (( )) los operadores para la comparación aritmética son == , !=, <, <=, > y >=.

    No, esto no es un «Aritmo expansión etic «(que comienzan con $) como $(( )). Se define como un «Comando compuesto» en man bash.

    Sí, sigue las mismas reglas (internamente) de la «Expansión aritmética» pero no tiene salida, solo un valor de salida. Podría usarse así:

if (( 2 > 1 )); then ... 

¿Por qué tenemos dos formas diferentes de comparar dos enteros?

Supongo que el último (( )) se desarrolló como una forma más sencilla de realizar pruebas aritméticas. Es casi lo mismo que $(( )) pero simplemente no tiene salida.

¿Por qué dos? Bueno, lo mismo que por qué tenemos dos printf (externo e integrado) o cuatro pruebas (externo test, interno test, [ y [[). Esa es la forma en que crecen las cáscaras, mejorando un área en un año, mejorando otras el próximo año.

¿Cuándo usar cuál?

Esa es una pregunta muy difícil porque no debería haber una diferencia efectiva. Por supuesto, existen algunas diferencias en la forma en que un [ ] funciona y un (( )) funciona internamente, pero: ¿cuál es mejor para comparar dos enteros? ¡Cualquiera!

Al comparar dos números enteros, ¿estos dos métodos se pueden usar siempre indistintamente?

Para dos números, me veo obligado a decir que sí.
Pero para las variables, las expansiones , operaciones matemáticas puede haber diferencias clave que deberían favorecer a una u otra. No puedo decir que absolutamente ambos sean iguales. Por un lado, (( )) podría realizar varias operaciones matemáticas en secuencia:

if (( a=1, b=2, c=a+b*b )); then echo "$c"; fi 

Si es así, ¿por qué Bash tiene ¿dos métodos en lugar de uno?

Si ambos son útiles, ¿por qué no?

Comentarios

  • = es una asignación y == es una comparación en expansiones aritméticas. La pregunta la cita correctamente. Pero la respuesta es incorrecta.
  • Además, ( no es una palabra reservada en bash, por lo que no es necesario poner espacios alrededor de ((, ya que opuesto a [ o [[

Respuesta

Históricamente, el comando test existía primero (al menos desde Unix Seventh Edition en 1979). Usó los operadores = y != para comparar cadenas y -eq, -ne, -lt, etc. para comparar números. Por ejemplo, test 0 = 00 es falso, pero test 0 -eq 00 es verdadero. No sé por qué se eligió esta sintaxis, pero puede haber sido para evitar el uso de < y >, que el shell habría analizados como operadores de redirección. El comando test obtuvo otra sintaxis unos años después: [ … ] es equivalente a test ….

La [[ … ]] sintaxis condicional, dentro de la cual < y > se pueden usar como operadores sin comillas, se agregó más tarde, en ksh. Mantuvo la compatibilidad con [ … ], por lo que usó los mismos operadores, pero agregó < y > para comparar cadenas (por ejemplo, [[ 9 > 10 ]] pero [[ 9 -lt 10 ]]). Para obtener más información, consulte usando corchetes simples o dobles – bash

Las expresiones aritméticas también vinieron después de test comando,

en el shell de Korn , en algún momento de la década de 1980. Siguieron la sintaxis del lenguaje C, que era muy popular en los círculos de Unix. Por lo tanto, utilizaron los operadores de C:==para igualdad,<=para menor o igual, etc.

La séptima edición de Unix no tenía expresiones aritméticas, pero tenía el comando expr , que también implementó un Sintaxis similar a C para operaciones con números enteros, incluidos sus operadores de comparación. En un script de shell, los caracteres < y > tenían que ser entrecomillados para protegerlos del shell, p. Ej. if expr 1 \< 2; … es equivalente a if test 1 -lt 2; …. La adición de expresiones aritméticas al shell hizo que la mayoría de los usos de expr fueran obsoletos, por lo que «no es muy conocido hoy en día.

En un script sh,» d generalmente usamos expresiones aritméticas para calcular un valor entero y [ … ] para comparar enteros.

if [ "$((x + y))" -lt "$z" ]; then … 

En un ksh , bash o zsh, puede utilizar ((…)) para ambos.

if ((x + y < z)); then … 

El es útil si desea utilizar condicionales que involucren cosas que no sean números enteros.

Respuesta

De acuerdo con la página de manual de prueba, = y! = se utilizan para comparaciones de cadenas, mientras que las expresiones -eq, -gt, -lt, -ge, -le y -ne son comparaciones de enteros. Siempre he seguido esta convención al escribir scripts de shell y siempre funciona. Tenga en cuenta que si tiene variables en la expresión, es posible que deba citar las variables de alguna manera para evitar hacer una comparación nula.

En el papel, hacemos comparaciones de cadena / número sin pensarlo mucho. Por otro lado, una computadora no sabe si 987 es un número o una cadena de caracteres. Necesita que los diferentes operadores le digan a la computadora qué hacer para obtener el resultado correcto. Hay información adicional aquí que explica parte de la historia. Básicamente, las variables no están escritas y se han mantenido así por compatibilidad histórica.

Comentarios

  • En mi publicación, = y != son operadores aritméticos, mientras que la página de manual de test solo muestra operadores de expresiones condicionales.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *