Pour être sûr, j'aimerais que bash abandonne l'exécution d'un script s'il rencontre une erreur de syntaxe.
À ma grande surprise, je ne peux pas y arriver. ( set -e
ne suffit pas.) Exemple:
#!/bin/bash
# Do exit on any error:
set -e
readonly a=(1 2)
# A syntax error is here:
if (( "${a[#]}" == 2 )); then
echo ok
else
echo not ok
fi
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Résultat (bash-3.2.39 ou bash-3.2.51):
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 10: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
Eh bien, nous ne pouvons pas vérifier $?
après chaque instruction pour détecter les erreurs de syntaxe.
(Je m'attendais à un tel comportement sûr d'un langage de programmation raisonnable ... peut-être que cela doit être signalé comme un bug / souhait de bash développeurs)
Plus d'expériences
if
ça ne fait aucune différence.
Suppression if
:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
(( "${a[#]}" == 2 ))
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Résultat:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
Peut-être que cela est lié à l'exercice 2 de http://mywiki.wooledge.org/BashFAQ/105 et a quelque chose à voir avec (( ))
. Mais je trouve toujours déraisonnable de continuer à exécuter après une erreur de syntaxe.
Non, (( ))
cela ne fait aucune différence!
Il se comporte mal même sans le test arithmétique! Juste un script simple et basique:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
echo "${a[#]}"
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Résultat:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
la source
set -e
n'est pas suffisant car votre erreur de syntaxe se trouve dans uneif
instruction. N'importe où ailleurs devrait abandonner le script.set -e
n'a pas fonctionné. Mais ma question a toujours un sens. Est-il possible d'interrompre une erreur de syntaxe?Réponses:
Envelopper le tout dans une fonction semble faire l'affaire:
Résultat:
Bien que je ne sache pas pourquoi - peut-être que quelqu'un d'autre peut expliquer?
la source
echo 'Bad2: has not aborted the execution after bad main!'
en dernier à votre exemple, et la sortie est: $ LC_ALL = C ./sh-on-syntax-err ./sh-on-syntax-err: ligne 6: #: erreur de syntaxe: opérande attendu ( le jeton d'erreur est "#") Bad2: n'a pas interrompu l'exécution après une mauvaise connexion principale! $Vous vous trompez probablement sur la véritable signification de
set -e
. Une lecture attentive de la sortie deshelp set
spectacles:Il
-e
s'agit donc de l'état de sortie des commandes non nulles, pas des erreurs de syntaxe dans votre script.En général, il est considéré comme une mauvaise pratique à utiliser
set -e
, car toutes les erreurs (c'est-à-dire tous les retours non nuls des commandes) doivent être intelligemment gérées par le script (pensez à un script robuste, pas à ceux qui se déchaînent après avoir entré un nom de fichier avec un espace ou qui commence par un hypen).Selon le type d'erreur de syntaxe, le script peut même ne pas être exécuté du tout. Je ne connais pas suffisamment bash pour dire exactement quelle classe d'erreurs de syntaxe (si seulement elles peuvent être classées) pourrait conduire à un avortement immédiat du script ou non. Peut-être que certains gourous Bash se joindront à eux et clarifieront tout.
J'espère seulement avoir clarifié la
set -e
déclaration!A propos de votre souhait:
La réponse est définitivement non! car ce que vous avez observé (
set -e
ne pas répondre comme vous vous y attendiez) est en fait très bien documenté.la source
set -e
- c'est juste un peu proche de mes objectifs, c'est pourquoi il est mentionné et utilisé ici. Ma question ne porte pas surset -e
la sécurité de bash si elle ne peut pas être interrompue en cas d'erreur de syntaxe. Je cherche un moyen de faire toujours avorter les erreurs de syntaxe.Vous pouvez faire vérifier le script lui-même en mettant quelque chose comme
près du haut du script - après
set -e
mais avant tout élément significatif de code.Je dois dire que cela ne semble pas très robuste, mais si cela fonctionne pour vous, c'est peut-être acceptable.
la source
set -e
:bash -n "$0" || exit
Tout d'abord, le
(( ))
in bash est utilisé comme calculs arithmétiques, à ne pas utiliser dans le if ... utilisez le[]
pour cela.Deuxièmement, le
${a[#]}
est bizarre et c'est pourquoi donne des erreurs ... le#
n'a pas de signification de tableauJe ne sais pas ce que vous voulez faire avec ça, mais je suppose que vous voulez connaître le nombre de champs, donc vous voulez
${#a[*]}
plutôtEnfin, lors de la comparaison d'entiers, le
-eq
est recommandé sur==
(utilisé pour les chaînes). la==
volonté fonctionne également, mais-eq
est recommandée.alors tu veux:
la source
((
mot - clé avec leif
mot - clé. Par exempleif (( 5 * $b > 53 ))
,. À moins que vous ne visiez la portabilité avec des obus plus anciens,[[
c'est généralement préférable à[
.[[
et((
ont été conçus spécifiquement comme des tests légers à utiliser avec "if", etc. - contrairement à cela[
, ils ne génèrent jamais un sous-processus pour évaluer la condition.[
est un bash intégré. Les coquilles plus anciennes s'attendent à ce que ce soit son propre programme.