Al fin después de tanto batallar pudimos hallar la contestación de este enigma que tantos usuarios de esta web han presentado. Si tienes alguna información que aportar no dejes de dejar tu conocimiento.
Solución:
Soltero []
son pruebas de condición compatibles con posix shell.
Doble [[]]
son una extensión del estándar []
y son compatibles con bash y otros shells (por ejemplo, zsh, ksh). Admiten operaciones adicionales (así como las operaciones posix estándar). Por ejemplo: ||
en lugar de -o
y expresiones regulares que coinciden con =~
. Se puede encontrar una lista más completa de diferencias en la sección del manual de bash sobre construcciones condicionales.
Usar []
siempre que desee que su secuencia de comandos sea portátil a través de shells. Usar [[]]
si desea expresiones condicionales no admitidas por []
y no necesita ser portátil.
Diferencias de comportamiento
Probado en Bash 4.3.11:
-
Extensión POSIX vs Bash:
[
is POSIX[[
is a Bash extension inspired from Korn shell
-
regular command vs magic
-
[
is just a regular command with a weird name.]
es solo el último argumento de[
.
Ubuntu 16.04 actually has an executable for it at
/usr/bin/[
provided by coreutils, but the bash built-in version takes precedence.Nothing is altered in the way that Bash parses the command.
In particular,
<
is redirection,&&
and||
concatenate multiple commands,( )
generates subshells unless escaped by, and word expansion happens as usual.
-
[[ X ]]
es una única construcción que haceX
ser analizado mágicamente.<
,&&
,||
y()
se tratan especialmente y las reglas de división de palabras son diferentes.También hay más diferencias como
=
y=~
.
En Bashese:
[
is a built-in command, and[[
is a keyword: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword -
-
<
[[ a < b ]]
: comparación lexicográfica[ a < b ]
: Lo mismo que arriba.requerido o de lo contrario hace la redirección como para cualquier otro comando. Extensión Bash.
expr x"$x" < x"$y" > /dev/null
o[ "$(expr x"$x" < x"$y")" = 1 ]
: Equivalentes POSIX, consulte: ¿Cómo probar cadenas lexicográficas menores o iguales en Bash?
-
&&
y||
[[ a = a && b = b ]]
: true, lógico y[ a = a && b = b ]
: error de sintaxis,&&
analizado como un separador de comandos ANDcmd1 && cmd2
[ a = a ] && [ b = b ]
: Equivalente confiable POSIX[ a = a -a b = b ]
: casi equivalente, pero en desuso por POSIX porque es una locura y falla para algunos valores dea
ob
igual que!
o(
que se interpretarían como operaciones lógicas
-
(
[[ (a = a || a = b) && a = b ]]
: false. Sin( )
, sería true porque[[ && ]]
tiene mayor precedencia que[[ || ]]
[ ( a = a ) ]
: error de sintaxis,()
se interpreta como una subcapa[ ( a = a -o a = b ) -a a = b ]
: equivalente, pero()
,-a
, y-o
están en desuso por POSIX. Sin( )
sería true porque-a
tiene mayor precedencia que-o
[ a = a ] && [ a = b ]
equivalente POSIX no obsoleto. Sin embargo, en este caso particular, podríamos haber escrito solo:[ a = a ] || [ a = b ] && [ a = b ]
porque el||
y&&
los operadores de shell tienen la misma precedencia a diferencia de[[ || ]]
y[[ && ]]
y-o
,-a
y[
-
word splitting and filename generation upon expansions (split+glob)
x='a b'; [[ $x = 'a b' ]]
: true, citas no necesariasx='a b'; [ $x = 'a b' ]
: error de sintaxis, se expande a[ a b = 'a b' ]
x='*'; [ $x = 'a b' ]
: error de sintaxis si hay más de un archivo en el directorio actual.x='a b'; [ "$x" = 'a b' ]
: Equivalente POSIX
-
=
[[ ab = a? ]]
: true, porque hace coincidir patrones (*? [
are magic). Does not glob expand to files in current directory.[ ab = a? ]
:a?
glob se expande. Así que tal vez true o false dependiendo de los archivos del directorio actual.[ ab = a? ]
: false, no expansión glob=
y==
son iguales en ambos[
and[[
, but==
is a Bash extension.case ab in (a?) echo match; esac
: POSIX equivalent[[ ab =~ 'ab?' ]]
: false, pierde magia con''
en Bash 3.2 y superior y la compatibilidad proporcionada con bash 3.1 no está habilitada (como conBASH_COMPAT=3.1
)[[ ab? =~ 'ab?' ]]
: true
-
=~
[[ ab =~ ab? ]]
: true, Coincidencia de expresión regular extendida POSIX,?
no se expande glob[ a =~ a ]
: error de sintaxis. Sin equivalente de bash.printf 'abn' | grep -Eq 'ab?'
: Equivalente a POSIX (solo datos de una sola línea)awk 'BEGINexit !(ARGV[1] ~ ARGV[2])' ab 'ab?'
: Equivalente a POSIX.
Recomendación: utilizar siempre []
Hay equivalentes POSIX para cada [[ ]]
construir que he visto.
Si utiliza [[ ]]
usted:
- perder portabilidad
- obligar al lector a aprender las complejidades de otra extensión de bash.
[
is just a regular command with a weird name, no special semantics are involved.
Thanks to Stéphane Chazelas for important corrections and additions.
Inside single brackets for condition test (i.e. [ ... ]), algunos operadores como single =
es compatible con todas las carcasas, mientras que el uso de operador ==
no es compatible con algunos de los shells más antiguos.
Entre paréntesis dobles para prueba de condición (es decir, [[ ... ]]), no hay diferencia entre usar =
o ==
en cáscaras viejas o nuevas.
Editar: También debo tener en cuenta que: En bash, siempre use corchetes dobles [[ ... ]]si es posible, porque es más seguro que los corchetes simples. Ilustraré por qué con el siguiente ejemplo:
if [ $var == "hello" ]; then
si $ var resulta ser null / vacío, entonces esto es lo que ve el script:
if [ == "hello" ]; then
que romperá tu guión. La solución es usar corchetes dobles o recordar siempre poner comillas alrededor de sus variables ("$var"
). Los corchetes dobles son una mejor práctica de codificación defensiva.
Aquí puedes ver las comentarios y valoraciones de los lectores
Tienes la opción de avalar nuestra publicación mostrando un comentario y valorándolo te damos la bienvenida.