web-dev-qa-db-fra.com

Comment fractionner une commande Shell sur plusieurs lignes lors de l'utilisation d'une instruction IF?

Comment fractionner une commande sur plusieurs lignes du shell lorsque la commande fait partie d'une instruction if?

Cela marche:

if ! fab --fabfile=.deploy/fabfile.py --forward-agent --disable-known-hosts deploy:$target; then rc=1                                                                       
fi

Cela ne marche pas:

# does not work:
if ! fab --fabfile=.deploy/fabfile.py \ 
  --forward-agent \
  --disable-known-hosts deploy:$target; then   
  rc=1
fi

Au lieu de l'exécution complète de la commande, je reçois:

./script.sh: line 73: --forward-agent: command not found

Plus important encore, qu'est-ce qui manque dans ma compréhension de Bash pour m'aider à comprendre cela et des problèmes similaires à l'avenir?

327
Dmitry Minkovsky

La continuation de ligne échouera si vous avez des espaces (espaces ou caractères de tabulation) après la barre oblique inverse et avant la nouvelle ligne. En l'absence de tels espaces, votre exemple me convient parfaitement:

$ cat test.sh
if ! fab --fabfile=.deploy/fabfile.py \
   --forward-agent \
   --disable-known-hosts deploy:$target; then
     echo failed
else
     echo succeeded
fi

$ alias fab=true; . ./test.sh
succeeded
$ alias fab=false; . ./test.sh
failed

Quelques détails mis en avant dans les commentaires: la barre oblique inverse de continuation de ligne dans le shell n’est pas vraiment un cas particulier; il s'agit simplement d'un exemple de la règle générale selon laquelle une barre oblique inverse "cite" le caractère qui suit immédiatement, empêchant ainsi tout traitement spécial auquel elle serait normalement soumise. Dans ce cas, le caractère suivant est un saut de ligne et le traitement spécial évité met fin à la commande. Normalement, un caractère cité finit inclus littéralement dans la commande; un retour à la ligne inversé est à la place entièrement supprimé. Mais sinon, le mécanisme est le même. Et la barre oblique inverse ne cite que le caractère qui suit immédiatement; si ce caractère est un espace ou une tabulation, vous obtenez simplement un espace ou une tabulation entre guillemets, et toute nouvelle ligne subséquente reste non citée.

502
Mark Reed

Pour les utilisateurs de Windows/WSL/Cygwin etc:

Assurez-vous que vos fins de ligne sont des sauts de ligne Unix standard, c'est-à-dire \n (LF) uniquement.

Utilisation des fins de ligne Windows \r\n (CRLF) Les fins de ligne interrompent la rupture de ligne de commande.


En effet, le fait que \ à la fin d'une ligne avec une fin de ligne Windows se traduise par \\r\n.
Comme Mark l'explique correctement ci-dessus:

La continuation de ligne échouera si vous avez des espaces après la barre oblique inverse et avant la nouvelle ligne.

Cela inclut non seulement l'espace () ou les tabulations (\t), mais également le retour chariot (\r).

44
Czechnology