3.4. Expansiones y sustituciones

Como se vio en el apartado de Funcionamiento general del shell, en un paso previo a la ejecución del elemento ejecutable se realizan una serie de expansiones y sustituciones. En este apartado se describe cuáles son y cómo se realizan. Puede ver una descripción detallada en el apartado 2.6 del estándar.

Existen los siguientes tipos de expansiones y sustituciones (que desarrollaremos más adelante):

  1. Expansión de ~ (virgulilla o tilde de la ñ).

  2. Expansión de parámetros o variables.

  3. Sustitución de comando.

  4. Expansión aritmética.

  5. Expansión de ruta.

Aparte de estas expansiones está el concepto de alias (ver apartado 2.3.1 del estándar) que se utiliza para crear sinónimos de comandos y sólo se realiza en el elemento ejecutable de la línea antes de cualquier otra expansión o sustitución. Su utilización es muy limitada y puede conseguirse un comportamiento similar usando funciones que permiten además parámetros (las funciones se verán más adelante). Puede ver los alias definidos usando el comando alias. Puede ver ejemplos de definición de alias en el fichero ~/.bashrc.

El orden de ejecución de estas expansiones es el siguiente:

  1. Primero se hacen en orden las siguientes expansiones:

    • Expansión de ~.

    • Expansión de parámetros o variables.

    • Sustitución de comando.

    • Expansión aritmética.

  2. Los campos generados en el primer paso son divididos utilizando como separadores los caracteres de la variable IFS. Si la variable IFS es nula (cadena nula) no se produce la división. Si la variable no está definida, se utilizan por defecto los caracteres espacio, tabulador y nueva línea.

  3. Se realiza a continuación la última expansión:

  4. Expansión de ruta.

  5. Por último, se eliminan las comillas simples o dobles que existan y se utilicen como tal (no se eliminan las comillas que hayan perdido su significado especial, por ejemplo usando el carácter de escape).

Puede utilizar las expansiones en cualquier ubicación donde se pueda usar una cadena de texto (incluido el nombre de comandos), exceptuando las palabras reservadas del lenguaje (if, else, …).

3.4.1. Expansión de ~

Las apariciones de la virgulilla (o tilde de la ñ) dentro de una línea, que no se encuentren entrecomilladas, se expanden de la siguiente manera:

~

Se expande al valor de la variable HOME

~login

Si «login» es un nombre de usuario del sistema, se expande a la ruta absoluta del directorio de inicio de sesión de ese usuario. Si no, no se expande.

Tareas

Comente la línea del script script_var-shell.sh, visto en el apartado 3.3, donde aparece la palabra «firefox». Ejecute los siguientes comandos observando el valor de las variables posicionales:

./script_var-shell.sh ~ ~root

./script_var-shell.sh ~noexiste ~dit

3.4.2. Expansión de parámetros y variables

El formato general para incluir una expansión de variables o parámetros, como se ha visto en apartados anteriores es:

${PAR}

Las llaves pueden omitirse, salvo cuando se trate de un parámetro posicional con más de un dígito o cuando se quiera separar el nombre de la variable de otros caracteres. Por ejemplo:

echo $PAR    #puede omitirse
echo ${10}   #no puede omitirse
${PAR}TEXTO  #no se omite

Si la expansión de parámetros ocurre dentro de comillas dobles, sobre el resultado no se realizará la expansión de ruta ni la división de campos (pasos b y c). En el caso del parámetro especial @, se hace la división de campos siempre.

Aparte de este formato general, se pueden utilizar otros formatos que permiten establecer valores por defecto, comprobar si la variable está definida, eliminar sufijos y prefijos, contar el número de caracteres, etc. Puede ver la lista de formatos junto con ejemplos en el apartado 2.6.2 del estándar. Por ejemplo , los siguientes:

${PAR:-alternativo}

Valor de la variable. Si la variable no tiene ningún valor, la construcción se sustituye por el valor alternativo.

${PAR:=alternativo}

Ídem al anterior, pero asignando el valor alternativo a la variable.

${PAR%sufijo}

Elimina el sufijo más pequeño del valor de la variable. sufijo es un patrón como los utilizados en la expansión de ruta. Si en vez de % se pone %% se elimina el sufijo más grande.

${PAR#prefijo}

Elimina el prefijo más pequeño del valor de la variable. prefijo es un patrón como los utilizados en la expansión de ruta. Si en vez de # se pone ## se elimina el prefijo más grande.

Los siguientes scripts muestran un posible ejemplo de ambas construcciones:

script_expansion1.sh
#!/bin/sh
VAR=1
echo $VAR
unset VAR
echo ${VAR:-2}
echo $VAR
FICH=fichero.c
echo ${FICH%.c}.o
script_expansion2.sh
#!/bin/sh
VAR=1
echo $VAR
unset VAR
echo ${VAR:=2}
echo $VAR
FICH=/usr/bin/prueba
echo ${FICH##*/}

TAREAS

Mire el contenido de los scripts anteriores en su sistema, invóquelos y analice los resultados.

3.4.3. Sustitución de comando

Permite que la salida estándar de un programa se utilice como parte de la línea que se va a interpretar.

Existen dos opciones, con el mismo funcionamiento:

$(comando)

`comando`

En el segundo caso se está utilizando la tilde francesa o acento grave, que no debe confundirse con las comillas simples. Para escribirla, hay que pulsar la tecla correspondiente a ` y pulsar espacio.

El shell ejecutará comando, capturará su salida estándar y sustituirá $(comando) por la salida capturada.

Por ejemplo, para almacenar en una variable el nombre de todos los ficheros con extensión .sh del directorio actual, podría escribir:

VAR=`ls *.sh`

O, por ejemplo, para matar el proceso con nombre firefox-bin, podría usar:

kill -9 $(pidof firefox-bin)

3.4.4. Expansión aritmética

El formato para realizar una expansión aritmética es el siguiente:

$((expresión))

Permite evaluar las cadenas indicadas en la expresión como enteros, admitiendo gran parte de los operadores usados en el lenguaje C, pudiendo usar paréntesis como parte de la expresión y el signo - para números negativos (a las cadenas que contengan letras se les asigna el valor 0). Tras la evaluación aritmética, el resultado vuelve a ser convertido a una cadena. La conversión de un número a un carácter puede realizarse con $'\xxx' (en bash) o con '\xxx' (en dash), ambos con comillas simples, pero ello no está recogido en el estándar POSIX.

Si se usan variables en la expresión, no es necesario que vayan precedidas por el carácter $ si ya contienen un valor entero válido (sí es necesario para los parámetros posicionales y especiales).

Puede ver más detalles en el apartado 2.6.4 del estándar.

TAREAS

Mire el contenido del script script_expansion3.sh, que deberá contener lo siguiente:

script_expansion3.sh
#!/bin/sh
VAR=1
VAR=$VAR+1
echo $VAR
RES1=$(($VAR))+1
echo $RES1
VAR=1
RES2=$((VAR+1)) #VAR no necesita $
echo $RES2
VARb=b
echo $(($VARb+1)) #VARb necesita $

Compruebe que dispone del permiso de ejecución. Invóquelo mediante el comando:

./script_expansion3.sh

Analice el resultado.

3.4.5. Expansión de ruta

Los campos que incluyan los caracteres *, ? y [ (asterisco, interrogación y apertura de corchetes) no entrecomillados serán sustituidos por la lista de ficheros que cumplan ese patrón. Si no hay ningún fichero con ese patrón no se sustituye nada. Puede ver más detalles en el apartado 2.13 del estándar.

TAREAS

Utilice el script script_var-shell.sh, visto en el apartado 3.3, pero modifíquelo eliminando las líneas con la palabra «firefox»,  para evitar que moleste en las siguientes pruebas. Ejecute los siguientes comandos observando el valor de la variable especial @:

./script_var-shell.sh s*_for?.sh

./script_var-shell.sh s*_for*.sh

./script_var-shell.sh s*_exp*.sh

./script_var-shell.sh s*_exp*[12].sh

./script_var-shell.sh s*_e*.sh