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):
Expansión de ~ (virgulilla o tilde de la ñ).
Expansión de parámetros o variables.
Sustitución de comando.
Expansión aritmética.
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:
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.
Los campos generados en el primer paso son divididos utilizando como separadores los caracteres de la variable
IFS
. Si la variableIFS
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.Se realiza a continuación la última expansión:
Expansión de ruta.
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:
#!/bin/sh
VAR=1
echo $VAR
unset VAR
echo ${VAR:-2}
echo $VAR
FICH=fichero.c
echo ${FICH%.c}.o
#!/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:
#!/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