Estoy leyendo ejemplos de bash, ifpero algunos ejemplos están escritos entre corchetes:
if [ -f $param ]
then
#...
fi
otros con corchetes dobles:
if [[ $? -ne 0 ]]
then
start looking for errors in yourlog
fi
¿Cuál es la diferencia?
bash
if-statement
rkmax
fuente
fuente

Respuestas:
Las
[]pruebas de condición de cumplimiento posix son simples .Double
[[]]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 estándar posix). Por ejemplo: en||lugar de-oy 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 .Úselo
[]siempre que desee que su secuencia de comandos sea portátil entre shells. Úselo[[]]si desea expresiones condicionales que no son compatibles[]y no necesitan ser portables.fuente
[[ ]](por ejemplo, bash con#!/bin/basho#!/usr/bin/env bash), debe usar la opción portátil. Las secuencias de comandos que suponen que / bin / sh admite extensiones como esta se romperán en sistemas operativos como las recientes versiones de Debian y Ubuntu, donde ese no es el caso.Diferencias de comportamiento
Probado en Bash 4.3.11:
Extensión POSIX vs Bash:
[es POSIX[[es una extensión Bash¹ documentada en: https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructscomando regular vs magia
[es solo un comando regular con un nombre extraño.]es solo un argumento[que evita que se utilicen más argumentos.Ubuntu 16.04 en realidad tiene un ejecutable
/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 la redirección&&y||concatena múltiples comandos,( )genera subcapas a menos que se escapen\y la expansión de palabras ocurre como de costumbre.[[ X ]]es una construcción única que hace queXse analice mágicamente.<,&&,||Y()se tratan de forma especial, 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: /ubuntu/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. Bash extension.expr a \< b > /dev/null: POSIX equivalente², ver: ¿Cómo probar cadenas para lexicografía menor o igual en Bash?&&y||[[ a = a && b = b ]]: verdadero, lógico y[ a = a && b = b ]: error de sintaxis,&&analizado como un separador de comando ANDcmd1 && cmd2[ a = a -a b = b ]: equivalente, pero obsoleto por POSIX³[ a = a ] && [ b = b ]: POSIX y equivalente confiable([[ (a = a || a = b) && a = b ]]: falso[ ( a = a ) ]: error de sintaxis,()se interpreta como una subshell[ \( a = a -o a = b \) -a a = b ]: equivalente, pero()es obsoleto por POSIX{ [ a = a ] || [ a = b ]; } && [ a = b ]POSIX equivalente 5división de palabras y generación de nombre de archivo en expansiones (split + glob)
x='a b'; [[ $x = 'a b' ]]: cierto, no se necesitan citasx='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? ]]: cierto, porque hace coincidir patrones (* ? [son mágicos). No se expande globalmente a los archivos en el directorio actual.[ ab = a? ]:a?Glob se expande. Por lo tanto, puede ser verdadero o falso dependiendo de los archivos en el directorio actual.[ ab = a\? ]: falso, no expansión glob=y==son iguales en ambos[y[[, pero==es una extensión Bash.case ab in (a?) echo match; esac: Equivalente POSIX[[ ab =~ 'ab?' ]]: falso 4 , pierde magia con''[[ ab? =~ 'ab?' ]]: cierto=~[[ ab =~ ab? ]]: verdadero, la coincidencia de expresión regular extendida POSIX ,?no se expande globalmente[ a =~ a ]: error de sintaxis. Sin bash equivalente.printf 'ab\n' | grep -Eq 'ab?': Equivalente POSIX (solo datos de una línea)awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?': Equivalente POSIX.Recomendación : usar siempre
[].Hay equivalentes POSIX para cada
[[ ]]construcción que he visto.Si te
[[ ]]usas:[es solo un comando regular con un nombre extraño, no hay semántica especial involucrada.¹ Inspirado en la
[[...]]construcción equivalente en el shell Korn² pero falla para algunos valores de
aob(like+orindex) y hace una comparación numérica siay sebparecen a enteros decimales.expr "x$a" '<' "x$b"trabaja alrededor de ambos.³ y también falla para algunos valores de
aoblike!or(.4 en bash 3.2 y superior y la compatibilidad proporcionada a bash 3.1 no está habilitada (como con
BASH_COMPAT=3.1)5 aunque la agrupación (aquí con el
{...;}grupo de comandos en lugar del(...)cual se ejecutaría una subshell innecesaria) no es necesaria ya que los operadores de shell||y&&(en oposición a los operadores||y&&[[...]]o los operadores-o/-a[) tienen la misma prioridad. Entonces[ a = a ] || [ a = b ] && [ a = b ]sería equivalente.fuente
[]debe leerse como Mi preferencia : úsela[]si no desea perder la portabilidad . Como se indica aquí : si la portabilidad / conformidad con POSIX o BourneShell es una preocupación, se debe usar la sintaxis anterior. Si, por otro lado, el script requiere BASH, Zsh o KornShell, la nueva sintaxis suele ser más flexible, pero no necesariamente compatible con versiones anteriores. Prefiero ir[[ ab =~ ab? ]]si puedo y no me preocupa la compatibilidad con versiones anteriores queprintf 'ab' | grep -Eq 'ab?'Dentro de los corchetes individuales para la prueba de condición (es decir, [...]), algunos operadores como single
=son compatibles con todos los shells, mientras que el uso del operador==no es compatible con algunos de los shells más antiguos.Dentro de los corchetes dobles para la prueba de condición (es decir, [...]]), no hay diferencia entre usar
=o==en conchas 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 individuales. Ilustraré por qué con el siguiente ejemplo:
si $ var resulta ser nulo / vacío, entonces esto es lo que ve el script:
que romperá tu guión. La solución es usar corchetes dobles o siempre recordar poner comillas alrededor de sus variables (
"$var"). Los corchetes dobles son una mejor práctica de codificación defensiva.fuente
[[es una palabra clave bash similar a (pero más poderosa que) el[comando.Ver
http://mywiki.wooledge.org/BashFAQ/031 y http://mywiki.wooledge.org/BashGuide/TestsAndConditionals
A menos que esté escribiendo para POSIX sh, le recomendamos
[[.fuente
puede usar los corchetes dobles para la coincidencia de expresiones regulares ligeras, por ejemplo:
if [[ $1 =~ "foo.*bar" ]] ; then(siempre que la versión de bash que esté utilizando sea compatible con esta sintaxis)
fuente
El manual de Bash dice:
(El comando de prueba es idéntico a [])
fuente