Paramètres de script dans Bash

103

J'essaye de créer un script shell qui devrait être utilisé comme ceci:

ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt

Le script convertira alors le fichier image en fichier texte. Voici ce que j'ai proposé jusqu'à présent:

#!/bin/bash
export HOME=/home/kristoffer
/usr/local/bin/abbyyocr9 -rl Swedish -if ???fromvalue??? -of ???tovalue??? 2>&1

Mais je ne sais pas comment obtenir les valeurs -fromet -to. Des idées sur la façon de procéder?

Kristoffer
la source
6
vous devriez lire tldp.org/LDP/Bash-Beginners-Guide/html/…
Mehul Rathod

Réponses:

124

Les arguments que vous fournissez à un bashscript apparaîtront dans les variables $1et $2et $3où le nombre fait référence à l'argument. $0est la commande elle-même.

Les arguments sont séparés par des espaces, donc si vous fournissez le -fromet -todans la commande, ils finiront également dans ces variables, donc pour ceci:

./ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt

Tu auras:

$0    # ocrscript.sh
$1    # -from
$2    # /home/kristoffer/test.png
$3    # -to
$4    # /home/kristoffer/test.txt

Il peut être plus facile d'omettre le -fromet le -to, comme:

ocrscript.sh /home/kristoffer/test.png /home/kristoffer/test.txt

Ensuite, vous aurez:

$1    # /home/kristoffer/test.png
$2    # /home/kristoffer/test.txt

L'inconvénient est que vous devrez le fournir dans le bon ordre. Il existe des bibliothèques qui peuvent faciliter l'analyse des arguments nommés sur la ligne de commande, mais généralement pour les scripts shell simples, vous devez simplement utiliser la méthode la plus simple, si cela ne pose aucun problème.

Ensuite, vous pouvez faire:

/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1

Les guillemets doubles autour du $1et du $2ne sont pas toujours nécessaires mais sont conseillés, car certaines chaînes ne fonctionneront pas si vous ne les mettez pas entre guillemets doubles.

gitaarik
la source
69

Si vous n'êtes pas complètement attaché à l'utilisation de "from" et "to" comme noms d'options, il est assez facile de l'implémenter en utilisant getopts :

while getopts f:t: opts; do
   case ${opts} in
      f) FROM_VAL=${OPTARG} ;;
      t) TO_VAL=${OPTARG} ;;
   esac
done

getopts est un programme qui traite les arguments de ligne de commande et les analyse pour vous.

f:t:spécifie que vous attendez 2 paramètres contenant des valeurs (indiquées par les deux points). Quelque chose comme f:t:vdit qui -vne sera interprété que comme un drapeau.

optsest l'endroit où le paramètre actuel est stocké. La casedéclaration est l'endroit où vous allez traiter cela.

${OPTARG}contient la valeur suivant le paramètre. ${FROM_VAL}par exemple obtiendra la valeur /home/kristoffer/test.pngsi vous avez exécuté votre script comme:

ocrscript.sh -f /home/kristoffer/test.png -t /home/kristoffer/test.txt

Comme les autres le suggèrent, si c'est la première fois que vous écrivez des scripts bash, vous devriez vraiment lire quelques notions de base. Ce n'était qu'un tutoriel rapide sur la façon dont getoptsfonctionne.

Manny D
la source
1
Cela semble être une solution lisible. Comment spécifieriez-vous alors deux drapeaux?
Zelphir Kaltstahl
@Zelphir, vous pouvez spécifier deux ou plusieurs indicateurs en omettant simplement le ":" après l'indicateur. Par exemple, ce f:t:vssera-f some_f -t some_t -v -s
h_s
34

Utilisez les variables "$1", "$2", "$3"et ainsi de suite aux arguments d'accès. Pour accéder à tous, vous pouvez utiliser "$@", ou pour obtenir le nombre d'arguments $#(peut être utile pour vérifier trop peu ou trop d'arguments).

StianE
la source
24

Je devais m'assurer que mes scripts sont entièrement portables entre différentes machines, shells et même versions cygwin. De plus, mes collègues pour qui j'ai dû écrire les scripts sont des programmeurs, alors j'ai fini par utiliser ceci:

for ((i=1;i<=$#;i++)); 
do

    if [ ${!i} = "-s" ] 
    then ((i++)) 
        var1=${!i};

    elif [ ${!i} = "-log" ];
    then ((i++)) 
        logFile=${!i};  

    elif [ ${!i} = "-x" ];
    then ((i++)) 
        var2=${!i};    

    elif [ ${!i} = "-p" ]; 
    then ((i++)) 
        var3=${!i};

    elif [ ${!i} = "-b" ];
    then ((i++)) 
        var4=${!i};

    elif [ ${!i} = "-l" ];
    then ((i++)) 
        var5=${!i}; 

    elif [ ${!i} = "-a" ];
    then ((i++)) 
        var6=${!i};
    fi

done;

Raison d'être: j'ai également inclus un launcher.shscript, car toute l'opération comportait plusieurs étapes qui étaient quasi indépendantes les unes des autres (je dis "quasi", car même si chaque script pouvait être exécuté seul, ils étaient généralement tous exécutés ensemble ), et en deux jours, j'ai découvert qu'environ la moitié de mes collègues, étant des programmeurs et tous, étaient trop bons pour utiliser le fichier de lancement, suivre l '"utilisation" ou lire l'aide qui s'affichait à chaque fois qu'ils faisaient quelque chose mal et ils faisaient tout un gâchis, exécutant des scripts avec des arguments dans le mauvais ordre et se plaignant que les scripts ne fonctionnaient pas correctement. Étant le colérique que je suis, j'ai décidé de réviser tous mes scripts pour m'assurer qu'ils sont à l'épreuve des collègues. Le segment de code ci-dessus était la première chose.

user1628658
la source
2
J'aime ça. J'ajoute une section à la fin `else echo" Argument invalide: $ {! I} "((i ++))
fi`
6

Dans bash $1est le premier argument passé au script, le $2second et ainsi de suite

/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1

Vous pouvez donc utiliser:

./your_script.sh some_source_file.png destination_file.txt

Explication sur les guillemets doubles;

considérez trois scripts:

# foo.sh
bash bar.sh $1

# cat foo2.sh
bash bar.sh "$1"

# bar.sh
echo "1-$1" "2-$2"

Maintenant, invoquez:

$ bash foo.sh "a b"
1-a 2-b

$ bash foo2.sh "a b"
1-a b 2-

Lorsque vous invoquez, foo.sh "a b"il invoque bar.sh a b(deux arguments) et avec foo2.sh "a b"lui bar.sh "a b"(1 argument). Gardez toujours à l'esprit la façon dont les paramètres sont passés et développés dans bash, cela vous évitera beaucoup de maux de tête.

Jakub M.
la source