traduccion - bash scripting tutorial español
Diferencia entre corchetes simples y dobles en Bash (6)
Estoy leyendo bash ejemplos sobre if
pero algunos ejemplos están escritos con corchetes individuales:
if [ -f $param ]
then
#...
fi
otros con doble corchetes cuadrados:
if [[ $? -ne 0 ]]
then
start looking for errors in yourlog
fi
¿Cuál es la diferencia?
Dentro de los corchetes individuales para la prueba de condición (es decir [...]), algunos operadores como single =
son compatibles con todas las shells, mientras que el uso de operator ==
no es compatible con algunas de las shells más antiguas.
Dentro de los corchetes dobles para la prueba de condición (es decir [[...]]), no hay diferencia entre usar =
o ==
en las carcasas viejas o nuevas.
Editar: También debería tener en cuenta que: en bash, siempre use corchetes dobles [[...]] si es posible, ya que es más seguro que los corchetes individuales. Ilustraré por qué con el siguiente ejemplo:
if [ $var == "hello" ]; then
si $ var pasa a ser nulo / vacío, esto es lo que ve el script:
if [ == "hello" ]; then
que romperá tu script La solución es usar corchetes dobles, o siempre recuerde poner comillas alrededor de sus variables ( "$var"
). Los corchetes dobles son una mejor práctica de codificación defensiva.
Single []
son pruebas de condición que cumplen con el shell posix.
Double [[]]
son una extensión del estándar []
y son compatibles con bash y otras shells (por ejemplo, zsh, ksh). Admiten operaciones adicionales (así como las operaciones posix estándar). Por ejemplo: ||
en lugar de -o
y regex matching con =~
. Se puede encontrar una lista más completa de diferencias en la sección manual de bash sobre construcciones condicionales .
Utilice []
cada vez que desee que su script sea portable a través de shells. Utilice [[]]
si desea expresiones condicionales no admitidas por []
y no es necesario que sean portátiles.
puede usar los corchetes dobles para la coincidencia de expresiones regulares claras, por ejemplo:
if [[ $1 =~ "foo.*bar" ]] ; then
(siempre y cuando la versión de bash que esté utilizando admita esta sintaxis)
El manual de Bash dice:
Cuando se usa con [[, los operadores ''<'' y ''>'' ordenan lexicográficamente usando la configuración regional actual. El comando de prueba utiliza el orden ASCII.
(El comando de prueba es idéntico a [])
[[
es una palabra clave bash similar a (pero más poderosa que) el [
comando.
Ver
here y http://mywiki.wooledge.org/BashGuide/TestsAndConditionals
A menos que esté escribiendo para POSIX sh, le recomendamos [[
.
Diferencias de comportamiento
Probado en Bash 4.3.11:
Extensión POSIX vs Bash:
-
[
es POSIX -
[[
es una extensión de Bash
-
comando regular vs magia
[
es solo un comando regular con un nombre raro.]
es solo un argumento de[
que evita que se usen argumentos adicionales.Ubuntu 16.04 realmente tiene un ejecutable en
/usr/bin/[
provisto por coreutils, pero la versión bash incorporada tiene prioridad.Nada se altera en la forma en que Bash analiza el comando.
En particular,
<
es la redirección,&&
y||
concatenar múltiples comandos,( )
genera subcapas a menos que escapen con/
, y la expansión de palabras ocurre como de costumbre.[[ X ]]
es una construcción única que hace queX
se analice mágicamente.<
,&&
,||
y()
son tratados 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 ]
: lo mismo que arriba./
required o de lo contrario redirecciona como para cualquier otro comando. Bash extensión. - No pude encontrar una alternativa POSIX a esto, vea: ¿Cómo probar cadenas para menor o igual?
-
&&
y||
-
[[ a = a && b = b ]]
: verdadero, lógico y -
[ a = a && b = b ]
: error de sintaxis,&&
analizado como un separador de comandos ANDcmd1 && cmd2
-
[ a = a -ab = b ]
: equivalente, pero obsoleto por POSIX -
[ a = a ] && [ b = b ]
: recomendación de POSIX
-
(
-
[[ (a = a || a = b) && a = b ]]
: falso -
[ ( a = a ) ]
: error de sintaxis,()
se interpreta como una subcapa -
[ /( a = a -oa = b /) -aa = 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 = ''ab'' ]]
x=''a b''; [[ $x = ''ab'' ]]
: verdadero, no se necesitan citas -
x=''a b''; [ $x = ''ab'' ]
x=''a b''; [ $x = ''ab'' ]
: error de sintaxis, se expande a[ ab = ''ab'' ]
-
x=''a b''; [ "$x" = ''ab'' ]
x=''a b''; [ "$x" = ''ab'' ]
: equivalente
-
=
-
[[ ab = a? ]]
[[ ab = a? ]]
: verdadero, porque coincide con el patrón (* ? [
son mágicos). No se expande globalmente a los archivos en el directorio actual. -
[ ab = a? ]
[ ab = a? ]
:a?
glob se expande Entonces puede ser verdadero o falso dependiendo de los archivos en el directorio actual. -
[ ab = a/? ]
[ ab = a/? ]
: expansión falsa, no glob -
=
y==
son iguales en ambos[
y[[
, pero==
es una extensión de Bash. -
printf ''ab'' | grep -Eq ''a.''
: Equivalente a POSIX ERE -
[[ ab =~ ''ab?'' ]]
[[ ab =~ ''ab?'' ]]
: falso, pierde magia con''''
-
[[ ab? =~ ''ab?'' ]]
[[ ab? =~ ''ab?'' ]]
: cierto
-
=~
-
[[ ab =~ ab? ]]
[[ ab =~ ab? ]]
: true, coincidencia de expresión regular extendida POSIX ,? no se expande -
[ 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 visto.
Si usa [[ ]]
usted:
- perder portabilidad
- obligar al lector a aprender las complejidades de otra extensión de bash.
[
es solo un comando regular con un nombre extraño, no hay semántica especial involucrada.