Descubrí que configurar la extglob
opción Shell solo dentro de un compuesto produce fallas en los globos extendidos posteriores. ¿Es necesario configurar las opciones de Shell fuera de los comandos compuestos? No vi ninguna indicación de tal requisito en las páginas de manual de Bash.
Como ejemplo, el siguiente script funciona bien (se imprime a.0 a.1
):
#!/bin/bash
touch a.0 a.1 \
a.b.0 a.b.1
shopt -s extglob
ls "a."!(b*)
Sin embargo, si las dos últimas líneas se ejecutan como un comando compuesto, el script falla con el siguiente error:
syntax error near unexpected token `('
` ls "a."!(b*)'
Esto se probó utilizando las versiones de Bash de 4.2 a 4.4 y con una variedad decomandos compuestos:
(1) condicional --if
#!/bin/bash
touch a.0 a.1 \
a.b.0 a.b.1
if true; then
shopt -s extglob
ls "a."!(b*)
fi
(2) tirantes -{ }
#!/bin/bash
touch a.0 a.1 \
a.b.0 a.b.1
{
shopt -s extglob
ls "a."!(b*)
}
(3) subcapa -- ( )
:
#!/bin/bash
touch a.0 a.1 \
a.b.0 a.b.1
(
shopt -s extglob
ls "a."!(b*)
)
En todos los casos, si shopt
se mueve fuera del comando compuesto, el script se ejecuta correctamente.
Respuesta1
Ninguna parte de un comando compuesto se ejecuta antes de que se analice todo el comando, lo cual está documentado indirectamente en elOperación Shellsección del manual: toda la tokenización y el análisis se realizan antes de que se ejecute "el" comando. Al habilitarlo, extglob
se cambia la sintaxis del idioma al agregar nuevos operadores de coincidencia de patrones, que se reconocen durante la tokenización.
Debido a que el shopt
comando no se ha ejecutado en el momento en !(
que se alcanza, se ve como un intento de expansión del historial ( !
) o el operador de control (
, en lugar de !(
verse como un solo elemento (y lo mismo para @(
, etc., excepto que no hay ninguna expansión del historial). allá).
Cuando el análisis llega a ese token, cualquiera de los casos generalmente será un error, aunque !(...)
al comienzo de una línea o después time
hay una tubería de subcapa negada. " unexpected token `('
" significa que no pudo aceptar una expresión de subcapa en ese lugar.
Esto es algo molesto cuando desea habilitar extglob solo temporalmente en un subshell. Una solución alternativa es definir una función que utilice el glob que desea, luego volver a deshabilitar extglob yentoncesllame a la función desde el subshell con extglob habilitado:
shopt -s extglob
f() { ls "a."!(b*) ; }
shopt -u extglob
(
shopt -s extglob
f
)
Es muy torpe.
El mismo efecto ocurre si crea un alias dentro de un comando compuesto, porque también se procesan antes del análisis:
if true
then
alias foo=echo
foo bar
fi
foo xyz
se imprimirá foo: command not found
, y luego xyz
, porque el aliasescreado, pero no estará disponible hasta que if
esté terminado.