Estoy confundido con el uso de corchetes simples o dobles. Mira este código:
dir="/home/mazimi/VirtualBox VMs"
if [[ -d ${dir} ]]; then
echo "yep"
fi
Funciona perfectamente aunque la cadena contiene un espacio. Pero cuando lo cambio a un solo soporte:
dir="/home/mazimi/VirtualBox VMs"
if [ -d ${dir} ]; then
echo "yep"
fi
Dice:
./script.sh: line 5: [: /home/mazimi/VirtualBox: binary operator expected
Cuando lo cambio a:
dir="/home/mazimi/VirtualBox VMs"
if [ -d "${dir}" ]; then
echo "yep"
fi
Funciona bien. ¿Alguien puede explicar lo que está pasando? ¿Cuándo debo asignar comillas dobles alrededor de variables como "${var}"para evitar problemas causados por espacios?

Respuestas:
El único soporte
[es en realidad un alias para eltestcomando, es no sintaxis.Una de las desventajas (de muchos) del paréntesis simple es que si uno o más de los operandos que está tratando de evaluar devuelven una cadena vacía, se quejará de que esperaba dos operandos (binario). Es por eso que ves que la gente lo hace
[ x$foo = x$blah ], lasxgarantías de que el operando nunca se evaluará en una cadena vacía.El doble soporte
[[ ]], por otro lado, es sintaxis y es mucho más capaz que[ ]. Como descubrió, no tiene el problema de un solo operando y también permite más sintaxis tipo C con los>, <, >=, <=, !=, ==, &&, ||operadores.Mi recomendación es la siguiente: si su intérprete es
#!/bin/bash, entonces siempre use[[ ]]Es importante señalar que
[[ ]]no es compatible con todas las conchas POSIX, sin embargo muchas conchas que apoyan tales comozshyksh, además debashfuente
$fooes!o(o-n... Ese problema no está destinado a ser un problema con shells POSIX donde el número de argumentos (al lado[y]) no es mayor que cuatro.[ x$foo = x$blah ]es tan incorrecto como[ $foo = $bar ].[ "$foo" = "$bar" ]es correcto en cualquier shell compatible con POSIX,[ "x$foo" = "x$bar" ]funcionaría en cualquier shell similar a Bourne, peroxno es para los casos en que tiene cadenas vacías, sino dónde$foopuede estar!o-n...[no es precisamente un alias paratest. Si lo fuera, entoncestestaceptaría un corchete de cierre.test -n foo ]. Perotestno lo hace, y[requiere uno.[es idéntico atesttodos los demás aspectos, pero no es así comoaliasfunciona. Bash describe[ytestcomo shell incorporado , pero[[como una palabra clave de shell .>=y<=El
[comando es un comando ordinario. Aunque la mayoría de los shells lo proporcionan como una eficiencia incorporada, obedece las reglas sintácticas normales del shell.[es exactamente equivalente atest, excepto que[requiere un]como último argumento ytestno lo hace.Los corchetes dobles
[[ … ]]son sintaxis especial. Se introdujeron en ksh (varios años después[) porque[puede ser problemático de usar correctamente y[[permite algunas nuevas adiciones agradables que usan caracteres especiales de shell. Por ejemplo, puedes escribirporque toda la expresión condicional es analizada por el shell, mientras
[ $x = foo && $y = bar ]que primero se dividiría en dos comandos[ $x = fooy se$y = bar ]separaría por el&&operador. Del mismo modo, los corchetes dobles permiten cosas como la sintaxis de coincidencia de patrones, por ejemplo,[[ $x == a* ]]para probar si el valor dexcomienza cona; entre paréntesis, esto se expandiríaa*a la lista de archivos cuyos nombres comienzanaen el directorio actual. Los corchetes dobles se introdujeron por primera vez en ksh y solo están disponibles en ksh, bash y zsh.Dentro de los corchetes simples, debe usar comillas dobles alrededor de sustituciones variables, como en la mayoría de los otros lugares, porque son solo argumentos para un comando (que resulta ser el
[comando). Dentro de los corchetes dobles, no necesita comillas dobles, ya que el shell no divide ni engloba palabras: analiza una expresión condicional, no un comando.Sin embargo, una excepción es
[[ $var1 = "$var2" ]]cuando necesita las comillas si desea hacer una comparación de cadena byte a byte, de lo contrario,$var2sería un patrón para comparar$var1.Una cosa que no puede hacer
[[ … ]]es usar una variable como operador. Por ejemplo, esto es perfectamente legal (pero rara vez útil):En tu ejemplo
el comando dentro de la
ifes[con los 4 argumentos-d,/home/mazimi/VirtualBox,VMsy]. El shell analiza-d /home/mazimi/VirtualBoxy luego no sabe qué hacerVMs. Debería evitar la división de palabras${dir}para obtener un comando bien formado.En términos generales, siempre use comillas dobles alrededor de las sustituciones de variables y comandos a menos que sepa que desea dividir y pegar palabras en el resultado. Los principales lugares donde es seguro no usar las comillas dobles son:
foo=$bar(pero tenga en cuenta que necesita las comillas dobles enexport "foo=$bar"o en asignaciones de matriz comoarray=("$a" "$b"));casedeclaración:case $foo in …;=o de==operador (a menos que usted desea que la coincidencia de patrones):[[ $x = "$y" ]].En todo esto, es correcto usar comillas dobles, por lo que es mejor omitir las reglas avanzadas y usar las comillas todo el tiempo.
fuente
[hecho es del Sistema III en 1981 , pensé que era más viejo.Implícito en esta pregunta es
${variable_name}no significa lo que crees que hace ...... si cree que tiene algo que ver con problemas causados por espacios (en valores variables). es bueno para esto:
${variable_name}¡y nada más! 1 nosirve de nada a menos que lo esté siguiendo inmediatamente con un carácter que podría ser parte de un nombre de variable: una letra (-o-), un guión bajo () o un dígito (-). E incluso entonces, puedes solucionarlo:
${variable_name}AZaz_09No estoy tratando de desalentar su uso,
echo "${bar}d"es probable que sea la mejor solución aquí, sino de disuadir a las personas de depender de llaves en lugar de citas, o aplicar llaves instintivamente y luego preguntar: “Ahora, ¿también necesito citas ? " Siempre debe usar comillas a menos que tenga una buena razón para no hacerlo, y esté seguro de saber lo que está haciendo._________________
1 Excepto, por supuesto, el hecho de que las formas más elegantes de expansión de parámetros , por ejemplo, y se basan en la sintaxis. Además, es necesario utilizar , etc., para hacer referencia a los días 10, 11, etc., parámetros posicionales - cotizaciones no le ayudará con eso.
${parameter:-[word]}${parameter%[word]}${parameter}${10}${11}fuente
Para manejar espacios y caracteres especiales en blanco en variables, siempre debe rodearlos con comillas dobles. Establecer un IFS adecuado también es una buena práctica.
Recomendado: http://www.dwheeler.com/essays/filenames-in-shell.html
fuente