for array bash
Usando && después de un heredoc en bash (2)
Encadenando comandos en una sola línea.
Puede poner el operador de control &&
justo después de la palabra EOF
en su documento aquí y puede encadenar más de un comando:
cat > file <<-EOF && echo -n "hello " && echo world
Esperará su documento aquí y luego imprimirá hola mundo .
Ejemplo
$ cat > file <<-EOF && echo -n "hello " && echo world
> a
> b
> EOF
hello world
$ cat file
a
b
Encadenamiento de comandos tras el delimitador heredoc.
Ahora, si desea colocar los siguientes comandos después del heredoc , puede agruparlos entre llaves y continuar encadenando los comandos de la siguiente manera:
echo -n "hello " && { cat > file <<-EOF
a
b
EOF
} && echo world
Ejemplo
$ echo -n "hello " && { cat > file <<-EOF
> a
> b
> EOF
> } && echo world
hello world
$ cat file
a
b
Usando el set incorporado
Si va a utilizar set [-+]e
lugar de los comandos encadenados con &&
, debe observar que rodear una porción de código con set -e
y set +e
no es una alternativa directa y debe tener cuidado como explicado a continuación:
Comandos dependientes circundantes con set [-+]e
echo first_command
false # it doesnt stop the execution of the script
# surrounded commands
set -e
echo successful_command_a
false # here stops the execution of the script
echo successful_command_b
set +e
# this command is never reached
echo last_command
Como puede ver, si necesita continuar ejecutando comandos después de los comandos rodeados , esta solución no funciona.
group al rescate.
En su lugar, puede agrupar los comandos rodeados para crear una subshell de la siguiente manera:
echo first_command
false # it doesnt stop the execution of the script
# surrounded commands executed in a subshell
(
set -e
echo successful_command_a
false # here stops the execution of the group
echo successful_command_b
set +e # actually, this is not needed here
)
# the script is alive here
false # it doesnt stop the execution of the script
echo last_command
Por lo tanto, si necesita ejecutar algo más después de los comandos encadenados y desea utilizar el set
incorporado , considere los ejemplos anteriores.
Observe también lo siguiente sobre las subshells :
La sustitución de comandos, los comandos agrupados con paréntesis y los comandos asíncronos se invocan en un entorno de subshell que es un duplicado del entorno de shell, excepto que las capturas capturadas por el shell se restablecen a los valores que el shell heredó de su padre en la invocación. Los comandos incorporados que se invocan como parte de una canalización también se ejecutan en un entorno de subshell. Los cambios realizados en el entorno de subshell no pueden afectar el entorno de ejecución del shell.
Tengo un script de bash cuyos comandos &&
usando &&
, ya que quiero que el script se detenga si fallan los pasos individuales.
Uno de los pasos crea un archivo de configuración basado en un heredoc:
some_command &&
some_command &&
some_command &&
some_command &&
some_command &&
some_command &&
cat > ./my-conf.yml <<-EOF
host: myhost.example.com
... blah blah ...
EOF
... lots more commands ...
¿Cómo puedo incluir este comando en la cadena &&
? Lo intenté:
- Colocando el
&&
inmediatamente después del EOF. No funciona como el EOF tiene que estar en una línea por sí mismo. - Colocar el
&&
en una línea por sí mismo siguiendo el EOF. No funciona porque Bash cree que estoy tratando de usar&&
como un comando. - Colocando el
&&
antes del redirector. No funcionó, ya que los redirectores son lógicamente parte del comando que se está&&
ed.
ACLARACIÓN:
Hay muchos comandos (multilínea) que siguen al comando que genera el archivo de configuración desde el heredoc, así que lo ideal es que busque una solución que me permita colocar los siguientes comandos después del heredoc, que es el flujo natural del script. Es decir, preferiría no tener que incluir más de 20 comandos en línea en una sola línea.
Si está utilizando el operador && solo para detener el comando que falla y no continuar, es posible que desee rodear el fragmento de código con set -e y cerrar con set + e. de esa manera, puede eliminar el && y su código probablemente se verá más limpio.