Diferencia entre comillas dobles, comillas simples y comillas invertidas en shell scripting
En GNU/Linux, cuando trabajamos con shell scripting, tenemos a nuestra disposición las «comillas dobles» y las ‘comillas simples’. Tenemos que tener claro cuales son sus diferencias, pues tanto al diseñar un script, como al utilizar la linea de comandos, el uso equivocado de comillas hará que no funcione lo que buscamos.
Es bastante habitual que los que están dando sus primeros pasos en shell scripting las confundan, incluso crean que son lo mismo. Aunque en determinadas circunstancias funcionan igual, existe una gran diferencia en como la shell bash las interpreta.
Un lector de este blog, me ha enviado un script que no le funcionaba y la solución es muy sencilla. Solo es problema del uso de las comillas. Luego lo veremos.
Sumario
- Diferencia entre comillas dobles y comillas simples
- Comillas dobles «
- Comillas simples ‘
- Comillas invertidas `
- Ejemplos
- Scrip de Javi
Diferencia entre comillas dobles y comillas simples
La diferencia está en como las interpreta el shell bash. Las comillas dobles permiten la expansión de las variables que definimos dentro de ellas. Con las comillas simples, el shell no interpretará las variables y hará una lectura literal del contenido. Vamos a verlo un poco mejor.
Comillas dobles
Las comillas dobles permiten a la shell interpretar unos caracteres especiales como son: el signo de «$», que indica que se trata de una variable, la tilde invertida «`», la barra invertida «\» o «slahs» y el signo de exclamación «!», que se usan en programación para diferentes propósitos.
Cuando usamos comillas dobles, todos los caracteres tienen un significado especial y, antes de mostrarse o ejecutarse, se evalúan. Podemos usar una comilla doble dentro de otra comilla, siempre que esté precedida de una barra invertida. A esto se le llama «escapar un caracter» y se hace para evitar que la shell lo interprete.
Las comillas dobles también se utilizan para encerrar frases que contienen espacios, generalmente nombres de ficheros o directorios. No obstante, si utilizas la linea de comandos habitualmente, es recomendable evitar los espacios. «nombre_del_fichero.extensión». Así será más fácil…
Como regla general podemos decir que lo que esté dentro de las comillas dobles se toma literalmente a excepción de los caracteres «$» sustitución de variable, «`» sustitución de comando y «\» caracter de escape.
Comillas simples
Las comillas simples las podemos utilizar cuando dentro de ellas no necesitemos expandir una variable. Estas mantendrán el valor literal de lo que contengan. El shell bash no interpretará nada, ni saltos ni ejecuciones. No tendrá en cuenta ni variables ni comillas inversas, ni escapes, etc…
Podemos decir que ningún caracter especial, incluido entre comillas simples, tendrá un significado especial. Por ello las utilizaremos cuando no queramos usar caracteres de escape, para modificar la forma en que bash interprete la cadena de entrada.
Comillas invertidas
Las comillas invertidas «`» son interpretadas como sustitución de comandos, es decir, los comandos que estén dentro serán pasados al comando que lo precede.
Vamos a verlo con unos ejemplos para que quede más claro.
Ejemplos
Si establecemos una variable en la linea de comandos, e imprimimos el resultado utilizando las comillas dobles obtendremos el siguiente resultado
var=javier echo "$var" javier
Pero si sustituimos las comillas dobles por simples el resultado será diferente, porque el shell no tendrá la capacidad de interpretar el signo del dolar «$» y por tanto no expandirá la variable. Se limitará a leer literalmente el contenido. Veamos,
var=javier echo '$var' $var
En español es raro, pero en inglés es habitual utilizar palabras que contienen una comilla. En estas situaciones tendremos un problema. Veámoslo,
echo 'Linux isn't Unix' > >
Se nos abre la consola esperando alguna orden. Si por el contrario, utilizamos comillas dobles, veamos que sucede,
echo "Linux isn't Unix" Linux isn't Unix
Por otro lado, si no utilizamos las comillas y ejecutamos
ls -l Mi directorio
La shell verá el comando «ls», la opción «-l» e interpretará «Mi» y «directorio» como dos argumentos. Vamos con más ejemplos
Si ejecutamos
export VAR="`ls | wc -l`" echo "$VAR"
Estamos asignando dinámicamente a la variable VAR el resultado que devuelve el comando entre las comillas simples, en este caso la cantidad de ficheros y directorios que existen en el directorio actual.
Si ejecutamos
echo "soy $USER y estoy en el directorio `pwd` que contiene `ls -d | wc -l` subdirectorios"
La variable $USER será interpretada, y los comandos «pwd» y «ls -d | wc -l», se ejecutarán. Prueba a ir cambiando las comillas y verás las diferencias por ti mismo. Te recomiendo que leas el manual ejecutando «man bash».
Scrip de Javi
Un lector de este blog, que está dando sus primeros pasos en shell scripting, me ha enviado un código que no le funcionaba. El problema es el uso de las comillas y alguna cosilla más. Es un script para sumar los tamaños de los ficheros que se le pasan como argumentos y, si alguno no existe o es un directorio, lo indique y lo excluya de la suma. Veamos el código que me ha enviado.
#!/bin/sh resultado=0 for h in $* do if [ -f $h ] then numero=`ls -l $h | tr -s " " " " | cut -f5 -d" "` resultado=`expr $resultado + $numero` else echo 'Uno de los argumentos no existe' fi done echo 'el tamaño sumado de los ficheros es $resultado bytes' exit 0
El script no te da el resultado esperado por las comillas. Además, las lineas
numero=`ls -l $h | tr -s " " " " | cut -f5 -d" "` resultado=`expr $resultado + $numero`
te darán un error, tienes que modificarlas por
export numero="`ls -l $h | tr -s " " " " | cut -f5 -d" "`" export resultado="`expr $resultado + $numero`"
O mejor por una sintaxis más moderna
numero=$(ls -l $h | tr -s " " " " | cut -f5 -d" ") resultado=$(expr $resultado + $numero)
Con algunas modificaciones y cambiando las comillas simples por dobles debe funcionar, porque está bien planteado. Pero te voy a dar unas recomendaciones adicionales.
Siempre que hagas un script, comienza por validar los argumentos. Te evitarás problemas futuros. Y tabula el código, será más fácil leerlo para depurarlo. Además siempre es recomendable añadir comentarios al código para interpretarlo.
Copia y pega, para probarlo, el siguiente código,
#!/bin/sh resultado=0 # #Validamos que se ha introducido un argumento # if [ $# -lt 1 ] then echo "Introduce, al menos, un argumento" exit 1 fi # #Programa principal # for h in $* do if [ -f $h ] then numero=$(ls -l $h | tr -s " " " " | cut -f5 -d" ") resultado=$(expr $resultado + $numero) else echo "Uno de los argumentos no existe o no es un fichero" fi done echo "la suma del tamaño de los ficheros es $resultado bytes" exit 0
Dale permisos de ejecución
chmod u+x nombre_del_script
y lo probamos
Si tienes algún comentario que hacer sobre este artículo, al pie del post tienes un formulario para hacerlo.
Si quieres contactar conmigo por cualquier otro asunto relacionado con el sitio, en la página de contacto, tienes un formulario más adecuado.
Y para suscribirte y recibir las novedades publicadas, tienes un enlace en el pie de la página o desde aquí mismo.
Buen trabajo Javier
Gracias Barto