Je ne comprends pas quel code d'erreur la commande retournera lors de l'exécution d'une affectation de variable de manière claire et avec substitution de commande:
a=$(false); echo $?
Il génère 1
, ce qui me laisse penser que l’affectation de variable ne balaye pas ou ne génère pas de nouveau code d’erreur sur le dernier. Mais quand j'ai essayé ceci:
false; a=""; echo $?
Il génère 0
, ce qui est évidemment ce que a=""
retourne et il remplace 1
renvoyé par false
.
Je veux savoir pourquoi cela se produit, y a-t-il une particularité dans l'affectation de variable qui diffère des autres commandes normales? Ou juste parce que a=$(false)
est considéré comme une commande unique et que seule une partie de substitution de commande a un sens?
-- METTRE À JOUR --
Merci à tous. D'après les réponses et les commentaires, je comprends que "lorsque vous affectez une variable à l'aide d'une substitution de commande, le statut de sortie correspond à celui de la commande." (par @Barmar), cette explication est extrêmement claire et facile à comprendre, mais le langage n'est pas assez précis pour les programmeurs, je souhaite voir la référence de ce point par des autorités telles que TLDP ou la page de manuel GNU, aidez-moi à le découvrir, merci encore!
Notez que ce n'est pas le cas lorsque vous utilisez local
dans une fonction. Ce qui est un comportement légèrement différent de celui décrit dans la réponse acceptée et le lien affiché ici: http://mywiki.wooledge.org/BashFAQ/002
Prenez ce script bash par exemple:
#!/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
Voici le résultat de ceci:
nick.parry@nparry-laptop1:~$ ./tmp.sh
output: Doing some stuff.
exitCode: 0
output: Doing some stuff.
exitCode: 1
Peut-être que personne ne s'en soucie, mais c'est ce que j'ai fait. Il m'a fallu une minute pour comprendre pourquoi mon code de statut était toujours 0 alors que ce n'était clairement pas parfois. Pas 100% clair pourquoi. Mais le simple fait de savoir que cela a aidé.
Je suis tombé sur le même problème hier (29 août 2018).
En plus de local
mentionné dans la réponse de Nick P. et le commentaire de @ sevko dans la réponse acceptée , declare
au niveau global ont également le même comportement.
Voici mon code 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"
Le résultat:
$ ./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
Notez les valeurs de local_ret2
et global_ret2
dans le résultat ci-dessus. Les codes de sortie sont remplacés par local
et declare
.
Ma version de Bash:
$ echo $BASH_VERSION
4.4.19(1)-release
(pas une réponse à la question initiale mais trop longue pour un commentaire)
Notez que export A=$(false); echo $?
génère 0! Apparemment, les règles citées dans la réponse de devnull ne s'appliquent plus. Pour ajouter un peu de contexte à cette citation (c'est moi qui souligne):
3.7.1 Extension de commande simple
...
S'il reste un nom de commande après le développement, l'exécution se poursuit comme décrit ci-dessous. Sinon, la commande se ferme. Si l'une des extensions contenait une substitution de commande, l'état de sortie de la commande est celui de la dernière substitution de commande effectuée. S'il n'y a aucune substitution de commande, la commande se termine avec un statut égal à zéro.
3.7.2 Recherche et exécution de commande [- c'est le cas "ci-dessous"]
Le manuel IIUC décrit var=foo
comme cas particulier de la syntaxe var=foo command...
(assez déroutant!). La règle "statut de sortie de la dernière substitution de commande" s'applique uniquement au cas de non-commande.
Bien qu'il soit tentant de penser à export var=foo
en tant que "syntaxe d'assignation modifiée", ce n'est pas - export
est une commande intégrée (qui prend juste des arguments semblables à ceux d'une affectation).
=> Si vous souhaitez exporter un statut de substitution de commande var AND capture, procédez en 2 étapes:
A=$(false)
# ... check $?
export A
Cette méthode fonctionne également en mode set -e
- quitte immédiatement si la substitution de commande retourne une valeur autre que 0.