web-dev-qa-db-fra.com

Quelle est la signification du paramètre -e pour la ligne de commande du shell bash?

J'ai comme script Shell bash avec en-tête #!/bin/bash -e.

Lorsque j'exécute le script, il est interrompu après l'exécution de la commande grep, mais lorsque je supprime le paramètre -e, le script peut alors être exécuté normalement. Quelle est la signification du paramètre -e?

64
Sam Ho

Le -e option signifie "si un pipeline se termine par un état de sortie non nul (" erreur "), arrêtez immédiatement le script". Puisque grep renvoie un état de sortie de 1 quand il ne trouve aucune correspondance, cela peut provoquer -e pour terminer le script même en l'absence d'une véritable "erreur".

Si vous souhaitez conserver le -e, mais également une commande grep qui pourrait ne trouver aucune correspondance valide, vous pouvez ajouter || : à la commande grep. Cela signifie "ou, si la commande grep renvoie un état de sortie différent de zéro, exécutez : (qui ne fait rien) "; l'effet net est donc de désactiver -e pour la commande grep. Alors:

grep PATTERN FILE... || :

Modifié pour ajouter: L'approche ci-dessus élimine toutes les erreurs: si grep renvoie 1 car il n'a trouvé aucune correspondance, c'est ignoré, mais aussi si grep renvoie 2 car il y a eu une erreur, elle est ignorée et si grep n'est pas dans le chemin (donc Bash retourne 127), c'est ignoré - et ainsi de suite. Donc, plutôt que :, il est probablement préférable d'utiliser une commande qui vérifie le code de résultat et ré-émet l'erreur si c'est autre chose que 1. Par exemple:

grep PATTERN FILE || (( $? == 1 ))

Mais cela détruit le statut de sortie; généralement, lorsqu'une commande ayant échoué termine un script Bash avec -e, le script renverra l'état de sortie de la commande, mais dans l'exemple ci-dessus, le script renverra simplement 1. Si (et seulement si) nous nous soucions de cela, nous pouvons y remédier en écrivant quelque chose comme ceci:

grep PATTERN FILE || exit_code=$?
if (( exit_code > 1 )) ; then
    exit $exit_code
fi

(première ligne c/o dsummersl commentaire de).

À ce stade, il est probablement préférable de créer une fonction Shell pour gérer cela pour nous:

function grep_no_match_ok () {
    local exit_code
    grep "$@" || exit_code=$?
    return $(( exit_code == 1 ? 0 : exit_code ))
}

(notez l'utilisation de return plutôt que exit; nous laisserons -e gérer la sortie le cas échéant); de cette façon, nous pouvons simplement écrire:

grep_no_match_ok PATTERN FILE     # won't kill script if no matches are found

En fait, puisque nous voulons très probablement utiliser cette fonction pour tous occurrences de grep dans ce script, nous pouvons en fait simplement nommer la fonction grep:

function grep () {
    local exit_code
    command grep "$@" || exit_code=$?
    return $(( exit_code == 1 ? 0 : exit_code ))
}

grep PATTERN FILE     # won't kill script if no matches are found

(notez l'utilisation de command pour contourner la fonction Shell dans son propre corps: nous voulons que la fonction appelle le programme régulier grep, plutôt que de récuser infiniment).

88
ruakh

Du manuel fin :

En plus des options de ligne de commande Shell à un seul caractère (voir Le jeu intégré), il existe plusieurs options à plusieurs caractères que vous pouvez utiliser.

Et puis si nous regardons ce que set a à dire:

-e
Quittez immédiatement si un pipeline (voir Pipelines), qui peut consister en une seule commande simple (voir Commandes simples), une commande de sous-shell entre parenthèses (voir Regroupement de commandes), ou l'une des commandes exécutées dans le cadre de une liste de commandes entourée d'accolades (voir Groupement de commandes) renvoie un état différent de zéro.

Donc, quand vous dites bash -e, si une commande du script échoue (c'est-à-dire renvoie un état d'existence différent de zéro), alors le script entier échoue immédiatement. Ainsi, votre grep renvoie une valeur non nulle car elle ne correspond pas et cela arrête tout le script si vous spécifiez -e lors de l'exécution de bash.

14
mu is too short