Expansión de una variable de caparazón y efecto de glob y división en ella

18

Esta publicación en realidad contiene dos preguntas separadas, pero creo que agruparlas juntas dará más contexto. He revisado esta pregunta sobre citas alrededor de variables, pero no entiendo qué significa expansión de variables en primer lugar. Entonces mi primera pregunta es:

  1. ¿Qué es la expansión variable en unix / linux speak?

Una segunda parte de mi pregunta se relaciona con los siguientes términos:

  1. glob
  2. división

¿Qué significa lo anterior y cómo afectan la expansión variable? La respuesta a la pregunta original menciona lo siguiente:

Piense en la ausencia de comillas (en contextos de lista) como el operador split + glob.

Como si echo $ test fuera echo glob (split ("$ test")).

No pude encontrar ninguna respuesta que aborde directamente el concepto de engorde y división, sino que utiliza esos términos directamente al responder otras preguntas como esta reciente .

Friki
fuente

Respuestas:

15

Expansión de variables (el término estándar es expansión de parámetros , y a veces también se llama sustitución de variables ) básicamente significa reemplazar la variable por su valor. Más precisamente, significa la sustitución de la $VARIABLEconstrucción (o ${VARIABLE}o ${VARIABLE#TEXT}o de otras construcciones) por algún otro texto que se construye a partir del valor de la variable. Este otro texto es la expansión de la variable.

El proceso de expansión es el siguiente. (Solo discuto el caso común, algunas configuraciones de shell y extensiones modifican el comportamiento).

  1. Tome el valor de la variable, que es una cadena. Si la variable no está definida, use la cadena vacía.
  2. Si la construcción incluye una transformación, aplíquela. Por ejemplo, si la construcción es ${VARIABLE#TEXT}, y el valor de la variable comienza con TEXT, elimine TEXTdesde el principio del valor.
  3. Si el contexto requiere una sola palabra (por ejemplo, entre comillas dobles, o en el lado derecho de una tarea, o dentro de un documento aquí), deténgase aquí. De lo contrario, continúe con los siguientes pasos.
  4. Divida el valor en palabras separadas en cada secuencia de espacios en blanco. (La variable IFSse puede cambiar para dividir en caracteres que no sean espacios en blanco). El resultado ya no es una cadena, sino una lista de cadenas. Esta lista puede estar vacía si el valor contenía solo espacios en blanco.
  5. Trate cada elemento de la lista como un patrón comodín de nombre de archivo, es decir, un globo . Si el patrón coincide con algunos archivos, se reemplaza por la lista de nombres de archivos coincidentes; de lo contrario, se deja solo.

Por ejemplo, suponga que la variable foocontiene a* b* c*y el directorio actual contiene los archivos bar, bazy paz. Luego ${foo#??}se expande de la siguiente manera:

  1. El valor de la variable es la cadena de 8 caracteres a* b* c*.
  2. #??significa quitar los dos primeros caracteres, lo que da como resultado la cadena de 6 caracteres  b* c*(con un espacio inicial).
  3. Si la expansión está en un contexto de lista (es decir, no entre comillas dobles u otro contexto similar), continúe.
  4. Divida la cadena en palabras delimitadas por espacios en blanco, dando como resultado una lista de dos cadenas: b*y c*.
  5. La cadena b*, interpretada como un patrón, coincide con dos archivos: bary baz. La cadena c*no coincide con ningún archivo, por lo que se deja sola. El resultado es una lista de tres cadenas: bar, baz, c*.

Por ejemplo, echo ${foo#??}imprime bar baz c*(el comando echoune sus argumentos con un espacio intermedio).

Para más detalles, ver:

Gilles 'SO- deja de ser malvado'
fuente
2
Tenga en cuenta que se llama la expansión de parámetro porque se aplica a variables ( $var) y otros tipos de parámetros como $1, $#, $?, $-...
Stéphane Chazelas
12

glob / split

Tomaré el glob / split primero. La respuesta de @ Stephane a la que se vinculó es usar esos términos en un sentido general. No son comandos reales ni nada por el estilo, solo pseudo operaciones.

El split("$test")dividiría el contenido de "$ test" en una "matriz" de elementos.

La glob(...)entonces tener cuidado para expandir cualquiera de estos elementos que contienen la cáscara globbing caracteres tales como *o rangos [1-2].

Ejemplo

Digamos que nuestra cadena $testes la siguiente.

$ test="afile[1-2] afile[3-5]"

También digamos que tenemos un directorio con algunos archivos.

$ ls -1
afile1
afile2
afile3
afile4
afile5

Ahora, si tratamos de repetirlo sin comillas, debería notar que nuestra cadena se dividió en espacios, y luego se expandió cualquier carácter global.

$ echo $test
afile1 afile2 afile3 afile4 afile5

Sin embargo, si tuviéramos que citar la variable cuando la pasamos como un argumento echo, obtendríamos la cadena literal original.

$ echo "$test"
afile[1-2] afile[3-5]

expansión variable

El término expansión variable está destinado a cubrir la operación básica que realiza el shell como parte de sus operaciones básicas. El shell es responsable de analizar la entrada y luego ejecutar esta entrada una vez que se considera sintácticamente correcta.

En nuestro ejemplo anterior. Cuando la variable $testse presentó sin echocomillas, le estábamos diciendo al shell que siguiera adelante y dividiera esos argumentos y luego los englobara.

Cuando fue citado, esencialmente estábamos deshabilitando esa característica con cualquier variable que envolviéramos con comillas dobles.

Ejemplo

Aquí hay algunos ejemplos adicionales de engrosamiento y división.

glob / división se produce automáticamente

$ echo file{1..3}
file1 file2 file3

$ echo file{1..3} dir{a..b}
file1 file2 file3 dira dirb

$ echo dir{z..w} file{A..D}
dirz diry dirx dirw fileA fileB fileC fileD

$ echo dir{z..w} file{A..B} fileC
dirz diry dirx dirw fileA fileB fileC

Glob / división deshabilitado mediante comillas dobles

$ echo "dir{z..w} file{A..B} fileC"
dir{z..w} file{A..B} fileC

$ echo "dir{z..w} file{A..B}"
dir{z..w} file{A..B}
slm
fuente
No sabía que los rangos también funcionaban en orden inverso.
Joe