¿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?
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
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).
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:
-
[
is POSIX -
[[
es una extensión 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 queX
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 Ycmd1 && 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.
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.
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.
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)
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.
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