¿Son preferibles los corchetes dobles []] sobre los corchetes simples [] en Bash?


Un compañero de trabajo afirmó recientemente en una revisión de código que la construcción [[ ]] debe ser preferida sobre [ ] en construcciones como

if [ "`id -nu`" = "$someuser" ] ; then 
     echo "I love you madly, $someuser"
fi

No pudo proporcionar una justificación. Hay uno?

Author: codeforester, 2009-03-21

7 answers

[[ tiene menos sorpresas y es generalmente más seguro de usar. Pero no es portable - POSIX no especifica lo que hace y solo algunos shells lo soportan (además de bash, he oído que ksh también lo soporta). Por ejemplo, puede hacer

[[ -e $b ]]

Para probar si existe un archivo. Pero con [, tienes que citar $b, porque divide el argumento y expande cosas como "a*" (donde [[ lo toma literalmente). Eso también tiene que ver con cómo [ puede ser un programa externo y recibe su argumento normalmente como cualquier otro programa (aunque también puede ser un builtin, pero entonces todavía no tiene este manejo especial).

[[ también tiene algunas otras características interesantes, como la expresión regular que coincide con =~ junto con operadores como se conocen en lenguajes similares a C. Aquí hay una buena página al respecto: ¿Cuál es la diferencia entre la prueba, [ y [[ ? y Pruebas Bash

 447
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-04 02:59:49

[[ ]] tiene más características-Le sugiero que eche un vistazo a Advanced Bash Scripting Guide para obtener más información, específicamente el comando de prueba extendido sección en Capítulo 7. Pruebas.

Por cierto, como señala la guía, [[ ]] se introdujo en ksh88 (la versión de 1988 del Korn shell).

 46
Author: Nils von Barth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-05 14:33:20

Diferencias de comportamiento

Primero, analicemos las diferencias de comportamiento entre ambos. Probado en Bash 4.3.11.

  • Extensión POSIX vs Bash:

  • Comando regular vs magia

    • [ es sólo un comando normal con un nombre raro.

      ] es solo un argumento de [ que impide que otros argumentos de siendo usado.

      Ubuntu 16.04 en realidad tiene un ejecutable para él en /usr/bin/[ proporcionado por coreutils, pero la versión integrada de bash tiene prioridad.

      Nada se altera en la forma en que Bash analiza el comando.

      En particular, < es redirección, && y || concatenan múltiples comandos, ( ) genera subcells a menos que se escapen por \, y la expansión de palabras ocurre como de costumbre.

    • [[ X ]] es una construcción única que hace que X se analice mágicamente. <, &&, || y () se tratan especialmente, y las reglas de división de palabras son diferentes.

      También Hay otras diferencias, como = y =~.

    En bashese: [ es un comando incorporado, y [[ es una palabra clave: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword

  • <

    • [[ a < b ]]: comparación lexicográfica
    • [ a \< b ]: Igual que arriba. \ requerido o de lo contrario hace redirección como para cualquier otro comando. Extensión Bash.
    • No pude encontrar una alternativa POSIX a esto, ver: ¿Cómo probar cadenas para menos o igual?
  • && y ||

    • [[ a = a && b = b ]]: verdadero, lógico y
    • [ a = a && b = b ]: error de sintaxis, && analizado como un separador de comandos Y cmd1 && cmd2
    • [ a = a -a b = b ]: equivalente, pero obsoleto por POSIX
    • [ a = a ] && [ b = b ]: POSIX recomendación
  • (

    • [[ (a = a || a = b) && a = b ]]: false
    • [ ( a = a ) ]: error de sintaxis, () se interpreta como una subcapa
    • [ \( a = a -o a = b \) -a a = b ]: equivalente, pero () está en desuso por POSIX
    • ([ a = a ] || [ a = b ]) && [ a = b ] Recomendación POSIX
  • División de palabras

    • x='a b'; [[ $x = 'a b' ]]: verdadero, no se necesitan comillas
    • x='a b'; [ $x = 'a b' ]: error de sintaxis, se expande a [ a b = 'a b' ]
    • x='a b'; [ "$x" = 'a b' ]: equivalente
  • =

    • [[ ab = a? ]]: verdadero, porque hace coincidencia de patrones (* ? [ son mágicas). No glob se expande a los archivos del directorio actual.
    • [ ab = a? ]: a? glob se expande. Así que puede ser verdadero o falso dependiendo de los archivos en el directorio actual.
    • [ ab = a\? ]: falso, no expansión global
    • = y == son lo mismo en ambos [ y [[, pero == es una extensión Bash.
    • printf 'ab' | grep -Eq 'a.': POSIX POSI equivalente
    • [[ ab =~ 'ab?' ]]: falso, pierde magia con {[57]]}
    • [[ ab? =~ 'ab?' ]]: verdadero
  • =~

    • [[ ab =~ ab? ]]: true, POSIX expresión regular extendida match, ? no glob expand
    • [ a =~ a ]: error de sintaxis
    • printf 'ab' | grep -Eq 'ab?': equivalente POSIX

Recomendación

Prefiero usar siempre [].

Hay equivalentes POSIX para cada construcción [[ ]] que he seen.

Si utilizas [[ ]]:

  • pierde portabilidad
  • obligar al lector a aprender las complejidades de otra extensión bash. [ es solo un comando regular con un nombre extraño, no hay semántica especial involucrada.
 28
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-06 01:01:29

Desde ¿Qué comparador, prueba, soporte o soporte doble es el más rápido? (http://bashcurescancer.com)

El soporte doble es un " compuesto comando" donde como prueba y el único soporte son shell incorporado (y en actualidad son el mismo comando). Así, el soporte simple y el soporte doble ejecutar código diferente.

La prueba y el soporte único son los más portátil, ya que existen como comandos separados y externos. Sin embargo, si su uso de cualquier remotamente versión moderna de BASH, el doble soporte es compatible.

 8
Author: f3lix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-21 15:34:15

Una situación típica donde no se puede usar [[es en un autotools configure.ac script, there brackets tiene un significado especial y diferente, por lo que tendrá que usar test en lugar de [ o [[Note Tenga en cuenta que test y [ son el mismo programa.

 1
Author: Vicente Adolfo Bolea Sánchez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-21 17:23:12

[[]] los corchetes dobles no se admiten bajo cierta versión de SunOS y totalmente no se admiten dentro de las declaraciones de función por : GNU bash, version 2.02.0 (1)-release (sparc-sun-solaris2.6)

 0
Author: scavenger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-19 14:59:51

En pocas palabras, [[ es mejor porque no horquilla otro proceso. Ningún soporte o un solo soporte es más lento que un soporte doble porque bifurca otro proceso.

 -1
Author: unix4linux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-24 16:08:48