Una razón simplificada es la existencia de un carácter: space.
Las expansiones de llaves no procesan espacios (sin comillas).
Una {...}
lista necesita espacios (sin comillas).
La respuesta más detallada es cómo el shell analiza una línea de comando .
El primer paso para analizar (comprender) una línea de comando es dividirla en partes.
Estas partes (generalmente llamadas palabras o tokens) resultan de dividir una línea de comando en cada metacarácter del enlace :
- Divide el comando en tokens que están separados por el conjunto fijo de metacaracteres: ESPACIO, TAB, NUEVA LÍNEA,;, (,), <,>, | y &. Los tipos de tokens incluyen palabras, palabras clave, redireccionadores de E / S y punto y coma.
Metacaracteres: spacetabenter;,<>|y &.
Después de dividir, las palabras pueden ser de un tipo (tal como lo entiende el shell):
- Comando pre-asignados:
LC=ALL ...
- Mando
LC=ALL echo
- Argumentos
LC=ALL echo "hello"
- Redireccionamiento
LC=ALL echo "hello" >&2
Expansión de la llave
Solo si una "cadena de llaves" (sin espacios o metacaracteres) es una sola palabra (como se describe anteriormente) y no se cita , es un candidato para la "expansión de llaves". Más controles se realizan en la estructura interna más adelante.
Por lo tanto, esto: {ls,-l}
califica como "expansión de llaves" para convertirse ls -l
, ya sea como first word
o argument
(en bash, zsh es diferente).
$ {ls,-l} ### executes `ls -l`
$ echo {ls,-l} ### prints `ls -l`
Pero esto no: {ls ,-l}
. Bash se dividirá spacey analizará la línea como dos palabras: {ls
y ,-l}
que activará a command not found
( ,-l}
se pierde el argumento ):
$ {ls ,-l}
bash: {ls: command not found
Su línea: {ls;echo hi}
no se convertirá en una "expansión de llaves" debido a los dos metacaracteres ;y space.
Se divide en tres partes esta: {ls
nuevo comando: echo
hi}
. Comprenda que ;desencadena el inicio de un nuevo comando. El comando {ls
no se encuentra, y el siguiente comando imprimirá hi}
:
$ {ls;echo hi}
bash: {ls: command not found
hi}
Si se coloca después de algún otro comando, de todos modos comenzará un nuevo comando después de ;:
$ echo {ls;echo hi}
{ls
hi}
Lista
Uno de los "comandos compuestos" es una "Lista Brace" (mis palabras): { list; }
.
Como puede ver, se define con espacios y un cierre ;
.
Los espacios y ;son necesarios porque ambos {
y }
son " palabras reservadas ".
Y por lo tanto, para ser reconocido como palabras, debe estar rodeado de metacaracteres (casi siempre:) space.
Como se describe en el punto 2 de la página vinculada
- Comprueba el primer token de cada comando para ver si es ..., {o (entonces el comando es en realidad un comando compuesto.
Tu ejemplo: {ls;echo hi}
no es una lista.
Necesita un cierre ;y un espacio (al menos) después {. El último }está definido por el cierre ;.
Esta es una lista { ls;echo hi; }
. Y esto { ls;echo hi;}
también es (menos utilizado, pero válido) (Gracias @choroba por la ayuda).
$ { ls;echo hi; }
A-list-of-files
hi
Pero como argumento (el shell conoce la diferencia) a un comando, desencadena un error:
$ echo { ls;echo hi; }
bash: syntax error near unexpected token `}'
Pero tenga cuidado con lo que cree que el shell está analizando:
$ echo { ls;echo hi;
{ ls
hi
{
interpretarse como una lista de comandos si aparece al comienzo de un comando y, de lo contrario, como una expansión de llaves, pero no estoy seguro.