Bash, avertissement sans arguments et décisions de cas

110

J'apprends bash.

Je voudrais faire un script simple qui, lorsqu'il n'est pas donné d'arguments, montre un message. Et quand je donne des nombres comme argument, en fonction de la valeur, cela fait une chose ou une autre.

J'aimerais également connaître les suggestions des meilleurs manuels en ligne pour les débutants en bash

Merci

Ouvrez la voie
la source

Réponses:

176
if [[ $# -eq 0 ]] ; then
    echo 'some message'
    exit 0
fi

case "$1" in
    1) echo 'you gave 1' ;;
    *) echo 'you gave something else' ;;
esac

Le guide Advanced Bash-Scripting est plutôt bon. Malgré son nom, il traite les bases.

Thomas
la source
RE: "sortie 0". Je ne sais pas si sortir du script était ce qu'il avait en tête. Mais oui, c'est un excellent guide.
Trampas Kirk
J'ai interprété "et" comme "autrement", en supposant que le message serait un texte d'aide. Mais je suis sûr que Werner est capable de comprendre ce que fait cette ligne et s'il le veut :)
Thomas
merci, bien sûr! et dernière chose, comment puis-je désactiver les messages d'erreur dans le script, afin qu'ils ne soient pas montrés au shell?
Ouvert le
Vous voulez dire les erreurs provenant d'un programme particulier que vous appelez? Vous pouvez mettre > /dev/nullet / ou 2> /dev/nullaprès cela pour envoyer sa sortie standard et / ou ses flux d'erreur standard dans l'oubli.
Thomas
4
Si vous considérez un argument manquant comme quelque chose de mauvais (comme le script ne peut alors pas s'exécuter correctement), renvoyez quelque chose de différent de 0 ( exit 1). Il existe d'autres conventions sur les codes retour / sortie, que vous pouvez trouver en ligne rapidement, mais le point important est qu'il ne doit pas être 0, ce qui indique un succès.
Felix
25

Si seulement intéressé à renflouer si un argument particulier est manquant, la substitution de paramètres est excellente:

#!/bin/bash
# usage-message.sh

: ${1?"Usage: $0 ARGUMENT"}
#  Script exits here if command-line parameter absent,
#+ with following error message.
#    usage-message.sh: 1: Usage: usage-message.sh ARGUMENT
Tapoter
la source
11

Exemple

 if [ -z "$*" ]; then echo "No args"; fi

Résultat

No args

Détails

-z est l'opérateur unaire pour la longueur de la chaîne est zéro. $*est tous les arguments. Les guillemets sont pour la sécurité et encapsulent plusieurs arguments s'ils sont présents.

Utilisez man bashet recherchez ( / key) pour "unaire" pour plus d'opérateurs comme celui-ci.

Trampas Kirk
la source
7
Un problème (mineur) avec ceci est qu'il ne fait pas la distinction entre passer aucun argument et passer une chaîne vide comme argument. Cela peut être important dans certains contextes. En utilisant [$ # -eq 0], on peut gérer correctement les deux cas.
Idelic
1
Ah, les subtilités de la programmation (ba) sh ... C'est pourquoi je déteste ça.
Thomas
1
penser -zà étourdir
Ray Foss
4

Vieux mais j'ai des raisons de retravailler la réponse maintenant grâce à une certaine confusion précédente:

if [[ $1 == "" ]] #Where "$1" is the positional argument you want to validate 

 then
 echo "something"
 exit 0

fi

Cela fera écho à "Quelque chose" s'il n'y a pas d'argument positionnel $ 1. Cependant, cela ne confirme pas que $ 1 contient des informations spécifiques.

Ryan Smith
la source
$#est explicitement le nombre entier du nombre d'arguments; ce sera soit "0", et vous ferez écho "quelque chose" même s'il n'y a pas d'arguments, ou ce sera un nombre positif, et vous ferez écho "quelque chose" correctement. Mais le contrôle lui-même ne fera jamais rien, indépendamment de l'entrée ou du manque d'entrée que vous utilisez - il rapportera toujours qui $#contient une valeur. C'est donc complètement faux et ne fonctionnera jamais comme prévu.
eschwartz
En êtes-vous tout à fait sûr? J'ai plusieurs scripts qui fonctionnent comme prévu en utilisant ce format exact. En lisant votre réponse, j'ai même retesté à la fois le match et son absence. $ # ne contiendra pas de valeur s'il n'est pas spécifié, s'il n'y a pas d'argument de position pour correspondre à ce qui se trouve dans votre scénario. Cela n'a aucun sens pourquoi bash prendrait une valeur dans un argument positionnel qui n'est pas là.
Ryan Smith
Essayez en echo $#tant que contenu d'un script /tmp/test.sh, puis exécutez-le sous / bin / bash ainsi que / bin / sh (ou / bin / dash et toute autre implémentation de shell dont vous disposez. /tmp/test.shFera écho "0" à la console, comme le fera /bin/dash /tmp/test.sh. D'autre part, /tmp/test.sh foofera écho "1", et /tmp/test.sh first secondfera écho "2".
eschwartz
Comme indiqué man bashdans la section "Paramètres spéciaux", "Le shell traite plusieurs paramètres spécialement. Ces paramètres ne peuvent être référencés que; leur affectation n'est pas autorisée.", Et "# S'étend au nombre de paramètres de position en décimal." Il est également mandaté par POSIX comme décrit dans pubs.opengroup.org/onlinepubs/9699919799/utilities/…
eschwartz
Désolé, il y a eu un problème de communication! Je voulais dire # comme espace réservé pour l'argument positionnel spécifique (c'est-à-dire $ 2 si vous vouliez dire le deuxième argument) et non littéral $ #. Après avoir examiné votre ci-dessus, vous avez tout à fait raison, un littéral $ # se résoudra toujours au nombre d'arguments. Toutes mes excuses pour la confusion.
Ryan Smith