pasar - programacion shell linux ejemplos
Salir del código de asignación de variable a sustitución de comando en Bash (4)
(no es una respuesta a la pregunta original, pero es demasiado tiempo para hacer comentarios)
Tenga en cuenta que export A=$(false); echo $?
export A=$(false); echo $?
¡salidas 0! Aparentemente, las reglas citadas en la respuesta de devnull ya no se aplican. Para agregar un poco de contexto a esa cita (el énfasis es mío):
3.7.1 Ampliación de comando simple
...
Si queda un nombre de comando después de la expansión, la ejecución continúa como se describe a continuación . De lo contrario , el comando sale. Si una de las expansiones contiene una sustitución de comando, el estado de salida del comando es el estado de salida de la última sustitución de comando realizada. Si no hubo sustituciones de comando, el comando sale con un estado de cero.
3.7.2 Búsqueda y ejecución de comandos [ este es el caso "a continuación" ]
IIUC el manual describe var=foo
como caso especial de var=foo command...
sintaxis (¡bastante confuso!). La regla de "estado de salida de la última sustitución de comando" solo se aplica al caso sin comando.
Si bien es tentador pensar en export var=foo
como una "sintaxis de asignación modificada", no lo es - export
es un comando integrado (que simplemente toma args similares a asignaciones).
=> Si desea exportar un estado de sustitución del comando var AND AND, hágalo en 2 etapas:
A=$(false)
# ... check $?
export A
De esta manera también funciona en modo set -e
mode - sale inmediatamente si la sustitución del comando devuelve no-0.
Estoy confundido acerca de qué código de error devolverá el comando al ejecutar una asignación de variable claramente y con la sustitución de comandos:
a=$(false); echo $?
Emite 1
, lo que me permite pensar que la asignación de variables no barre ni produce un nuevo código de error en el último. Pero cuando probé esto:
false; a=""; echo $?
Emite 0
, obviamente esto es lo que a=""
devuelve y reemplaza 1
devuelto por false
.
Quiero saber por qué sucede esto, ¿hay alguna particularidad en la asignación de variables que difiera de otros comandos normales? ¿O simplemente porque a=$(false)
se considera un solo comando y solo la parte de sustitución de comando tiene sentido?
- ACTUALIZACIÓN -
Gracias a todos, de las respuestas y comentarios obtuve el punto "Cuando asigna una variable usando la sustitución de comando, el estado de salida es el estado del comando". (por @Barmar), esta explicación es muy clara y fácil de entender, pero hablar no es lo suficientemente preciso para los programadores, quiero ver la referencia de este punto de autoridades como TLDP o la página de manual de GNU, ayúdenme a encontrarlo. fuera, gracias de nuevo!
Al ejecutar un comando como $(command)
permite que la salida del comando se reemplace .
Cuando tu dices:
a=$(false) # false fails; the output of false is stored in the variable a
la salida producida por el comando false
se almacena en la variable a
. Además, el código de salida es el mismo que el producido por el comando. help false
diría:
false: false
Return an unsuccessful result.
Exit Status:
Always fails.
Por otro lado, diciendo:
$ false # Exit code: 1
$ a="" # Exit code: 0
$ echo $? # Prints 0
hace que se devuelva el código de salida para la asignación a a que es 0
.
EDITAR:
Citando del manual :
Si una de las expansiones contiene una sustitución de comando, el estado de salida del comando es el estado de salida de la última sustitución de comando realizada.
Citando de BASHFAQ/002 :
¿Cómo puedo almacenar el valor de retorno y / o la salida de un comando en una variable?
...
output=$(command)
status=$?
La asignación a la
output
no tiene efecto en el estado de salida delcommand
, que todavía está en$?
.
Me encontré con el mismo problema ayer.
Además del local
mencionado en la respuesta de Nick P. y el comentario de @sevko en la respuesta aceptada , declare
en alcance global también tiene el mismo comportamiento.
Aquí está mi código Bash:
#!/bin/bash
func1()
{
ls file_not_existed
local local_ret1=$?
echo "local_ret1=$local_ret1"
local local_var2=$(ls file_not_existed)
local local_ret2=$?
echo "local_ret2=$local_ret2"
local local_var3
local_var3=$(ls file_not_existed)
local local_ret3=$?
echo "local_ret3=$local_ret3"
}
func1
ls file_not_existed
global_ret1=$?
echo "global_ret1=$global_ret1"
declare global_var2=$(ls file_not_existed)
global_ret2=$?
echo "global_ret2=$global_ret2"
declare global_var3
global_var3=$(ls file_not_existed)
global_ret3=$?
echo "global_ret3=$global_ret3"
La salida:
$ ./declare_local_command_substitution.sh 2>/dev/null
local_ret1=2
local_ret2=0
local_ret3=2
global_ret1=2
global_ret2=0
global_ret3=2
Tenga en cuenta los valores de local_ret2
y global_ret2
en el resultado anterior. Los códigos de salida son sobrescritos por local
y declare
.
Versión My Bash:
$ echo $BASH_VERSION
4.4.19(1)-release
Tenga en cuenta que este no es el caso cuando se usa local
dentro de una función. Que es un comportamiento sutilmente diferente de lo que se describe en la respuesta aceptada, y el enlace publicado aquí: BASHFAQ/002
Toma este script bash por ejemplo:
#!/bin/bash
function funWithLocalVar() {
local output="$(echo "Doing some stuff.";exit 1)"
local exitCode=$?
echo "output: $output"
echo "exitCode: $exitCode"
}
function funWithoutLocalVar() {
output="$(echo "Doing some stuff.";exit 1)"
local exitCode=$?
echo "output: $output"
echo "exitCode: $exitCode"
}
funWithLocalVar
funWithoutLocalVar
Aquí está el resultado de esto:
nick.parry@nparry-laptop1:~$ ./tmp.sh
output: Doing some stuff.
exitCode: 0
output: Doing some stuff.
exitCode: 1
Quizás a nadie le importa, pero lo hice. Me tomó un minuto averiguar por qué mi código de estado siempre era 0 cuando claramente no era a veces. No está 100% claro por qué. Pero el simple hecho de saber esto ayudó.