Pages : 1
#1 Le 14/07/2008, à 11:03
- Totor
[résolu?] [bash] - getopts
Bonjour,
getopts permet de traiter des options positionnels d'un script. Il s'agit des options spécifiés par le caractère "-" de la ligne de commande.
Mais quid des options/arguments commençant par "--" ? Est-ce [arguments] de getopts qui le permet ? Auquel cas, quel est son formalise ? Quel est le séparateur à utiliser permettant l'identification des différents arguments "--" autorisés (s'il y a un séparateur à mettre) ?
merci
Dernière modification par Totor (Le 15/07/2008, à 11:52)
-- Lucid Lynx --
Hors ligne
#2 Le 15/07/2008, à 10:46
- Totor
Re : [résolu?] [bash] - getopts
Après mult recherches sur le net sans succès, je me suis résigné à écrire une petite fonction vérifiant l'existance d'un paramétre en ligne de commande.
Les paramétres pouvant être valorisés. Cela donne donc le formalise suivant :
--<nom>[=<valeur>]
La fonction prend comme 1er argument le nom du paramétre à rechercher puis l'ensemble de la ligne de commande (sauf $0).
Si elle trouve le paramétre, elle valorise les variables globales OPT avec le nom du paramétre et VAL par sa valeur si elle est indiquée.
Il y a un cas "particulier" : si la valeur renseignée est constituée d'au moins un espace.
Je ne pense pas que cela vienne de la fonction mais plutôt de la façon de lui passer les paramétres. En effet, j'ai réalisé un test : avant l'appel à la fonction, j'affiche l'ensemble des paramétres un à un et je les retrouve très bien !
Voici le contenu du fichier utilisé pour tester (qui fait juste un appel à la fonction et affiche le résulat) :
#!/bin/ksh
export OPT=""
export VAL=""
function rechercheOption
{
option="$1"
shift
OPT=""
VAL=""
while [[ ! -z "$1" && -z "${OPT}" ]]
do
OPT="`echo "$1"| sed "/${option}/!d"`"
if [ ! -z "${OPT}" ]; then
VAL="`echo "$1"|sed "s#${option}[=]\{0,1\}##"`"
OPT="${option}"
fi
shift
done
}
rechercheOption $@
echo -e "option=${OPT}\tvaleur=${VAL}"
Un exemple de dysfonctionnement (on voit bien que "titi" est considéré comme un paramétre à part entère ) :
bash -x ./test --param2 --param1= --param2="toto titi"
+ export OPT=
+ OPT=
+ export VAL=
+ VAL=
+ rechercheOption --param2 --param1= --param2=toto titi
+ option=--param2
+ shift
+ OPT=
+ VAL=
+ [[ ! -z --param1= ]]
+ [[ -z '' ]]
++ echo --param1=
++ sed '/--param2/!d'
+ OPT=
+ '[' '!' -z '' ']'
+ shift
+ [[ ! -z --param2=toto ]]
+ [[ -z '' ]]
++ echo --param2=toto
++ sed '/--param2/!d'
+ OPT=--param2=toto
+ '[' '!' -z --param2=toto ']'
++ echo --param2=toto
++ sed 's#--param2[=]\{0,1\}##'
+ VAL=toto
+ OPT=--param2
+ shift
+ [[ ! -z titi ]]
+ [[ -z --param2 ]]
+ echo -e 'option=--param2\tvaleur=toto'
option=--param2 valeur=toto
Donc, ma question est : comment transmettre les paramétres à la fonction exactement de la même façon qu'ils ont été mis sur la ligne de commande ?
Note : pour afficher les paramétres de la ligne de commande, rajouter ce code :
i=1
while [ $i -le $# ]
do
echo "param $i=`eval echo \\$${i}`"
let i=i+1
done
Merci
-- Lucid Lynx --
Hors ligne
#3 Le 15/07/2008, à 11:49
- Totor
Re : [résolu?] [bash] - getopts
Bon, j'ai fini par trouvé une solution mais je ne trouve pas ça très propre
(Donc si vous avez une meilleure solution, elle est la bienvenue !)
La voici :
#!/bin/ksh
export OPT=""
export VAL=""
function rechercheOption
{
option="$1"
shift
OPT=""
VAL=""
while [[ ! -z "$1" && -z "${OPT}" ]]
do
OPT="`echo "$1"| sed "/${option}/!d"`"
if [ ! -z "${OPT}" ]; then
VAL="`echo "$1"|sed "s#${option}[=]\?##"`"
OPT="${option}"
fi
shift
done
}
ligneCmd="rechercheOption "
for valeur;
do
ligneCmd="${ligneCmd} \"${valeur}\""
done
eval ${ligneCmd}
echo -e "option=${OPT}\tvaleur=${VAL}"
Dernière modification par Totor (Le 15/07/2008, à 12:50)
-- Lucid Lynx --
Hors ligne
#4 Le 15/07/2008, à 13:07
- Totor
Re : [résolu?] [bash] - getopts
Correction d'un bug dans la fonction rechercheOption !
Pour le comprendre, le plus simple est d'utiliser l'ancienne version de la fonction avec les paramétres suivant :
--param2 --param1 --param2test --param2="#toto/\ titi#"
Résultat :
OPT prend la valeur --param2 --> ok
VAL prend la valeur test --> ko !
Mais bon, la correction :
#!/bin/ksh
export OPT=""
export VAL=""
function rechercheOption
{
option="$1"
shift
OPT=""
VAL=""
while [[ -n "$1" && -z "${OPT}" ]]
do
OPT="`echo "$1"| grep -o "^${option}\(=.*\)\?$"`"
if [ -n "${OPT}" ]; then
VAL="`echo "$1"|sed "s/${option}[=]\?//"`"
OPT="${option}"
fi
shift
done
}
ligneCmd="rechercheOption "
for valeur;
do
ligneCmd="${ligneCmd} \"${valeur}\""
done
eval ${ligneCmd}
echo -e "option=${OPT}\tvaleur=${VAL}"
Dernière modification par Totor (Le 15/07/2008, à 13:15)
-- Lucid Lynx --
Hors ligne
#5 Le 22/11/2008, à 23:35
- drfazor
Re : [résolu?] [bash] - getopts
il est possible de contourner la fonction getopts pour qu'elle accepte les arguments long, il suffit de fixer - comme option recevable avec argument. En voila un exemple de script:
#!/bin/bash
# Usage du programme
usage="
script [-b|--bash -p|--perl -f|--force -h|--help] fichier\n
\n
Cree un script dans le langage voulu\n
-b ou --bash: Creation d'un script en bash\n
-p ou --perl: Creation d'un script en perl\n
-f ou --force: Force a la réecriture d'un script\n
-h ou --help: dispense cette aide et quitte\n
"
# Definition des variables par defaut
shebang=""
force=0
# Lecture des options
while getopts "bpfh-:" option
do
if [ $option = "-" ]
then
case $OPTARG in
bash) option="b";;
perl) option="p";;
help) option="h";;
force) option="f";;
esac
fi
case $option in
b)shebang="#!/bin/bash";;
p)shebang="#!/bin/perl";;
f)force=1;;
h)echo $usage && exit 0;;
esac
done
# Place $1 après les options
shift $(($OPTIND-1))
# Création du chemin du fichier
fichier=$HOME/bin/$1
# Test de l'existance du fichier et de la valeur du flag
if [ -e $fichier ] && [ $force -eq 0 ]
then
echo "le fichier existe" && exit 1;
fi
# Creation et ecriture du fichier
echo $shebang > $fichier && chmod +x $fichier
# fin du script
En esperant que tu puisses en faire ton bonheur
#6 Le 25/11/2008, à 20:21
- Totor
Re : [résolu?] [bash] - getopts
Bonsoir,
Intéressant ! Merci pour cette astuce
-- Lucid Lynx --
Hors ligne
#7 Le 21/06/2011, à 18:09
- Hizoka
Re : [résolu?] [bash] - getopts
je deterre le sujet,
drfazor => avc ta facon de faire que ce passe-t-il si tu fais :
-test "oui - non.txt"
perso j'ai du me faire un systeme proche de getopts qui me permet de prendre en compte mes arguments longs mais mon élément séparateur c'est le -, donc si j'indique un fichier en contenant un ca ne passe plus...
KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github
Hors ligne
#8 Le 22/06/2011, à 15:35
- FRUiT
Re : [résolu?] [bash] - getopts
Ben ça marche plutôt très bien :
> cat getopts.example
#!/bin/bash
while getopts "abn:-:" O "$@"; do
[ "$O" = "-" ] && case $OPTARG in
test) O=t ;;
esac
case $O in
t) FILE="${!OPTIND}" ; let "OPTIND += 1" ;;
n) echo "$OPTARG" ;;
a) echo bar ;;
esac
done
shift $(($OPTIND-1))
echo "$FILE"
echo "$@"
> ./getopts.example -a --test "oui - non.txt" -n qux
bar
qux
oui - non.txt
>
Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean
Hors ligne
#9 Le 22/06/2011, à 17:17
- Hizoka
Re : [résolu?] [bash] - getopts
bon bah je vais modifier completement mon fichier pour y inclure ça alors
merci FRUiT !
tu peux m'expliquer :
FILE="${!OPTIND}" ; let "OPTIND += 1"
${!varprefixe*},${!varprefixe@}
Établit une correspondance des noms de toutes les variables déjà déclarées commençant par varprefixe.
mais là c'est pas le cas...
et pourquoi ajouter 1 à OPTIND ?
merci
KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github
Hors ligne
#10 Le 22/06/2011, à 18:15
- FRUiT
Re : [résolu?] [bash] - getopts
En fait c'est pour gérer les options suivantes le cas échéant (dans l'exemple « -n qux »).
Dans l' astuce de drfazor, l'option est « - », MAIS son $OPTARG associé est en fait le mot de l'option longue.
C'est ce qui se produit ici :
[ "$O" = "-" ] && case $OPTARG in
test) O=t ;;
esac
C'est bien OPTARG qui est testé dans le case (et il vaut « test » et pas le nom du fichier, argument réel de l'option longue), donc pour récupérer le nom de fichier qui suit, je ne peux pas me baser sur cette variable (déjà utilisée) comme dans l'exemple de l'option « -n ».
En suivant le raisonnement de getopts, nous avons donc l'option « -- » suivie du OPTARG « test ». Ce qui vient après « test » est le nom du fichier que je souhaite récupérer (l'argument réel de l'option --test). Ce nom ne commançant pas par « - », getopts détermine que les options sont terminées et que le nom du fichier ne fait pas partie des options, ainsi que toutes les options qui pourraient le suivre (ils sont alors considérés comme des paramètres positionnels quelconques à ne pas traiter). Donc non seulement si une option longue a un argument, on ne peut pas compter sur OPTARG pour le récupérer car déjà utilisé pour la ruse, mais cela induit en plus un décalage de 1 dans le traitement des options.
Car en effet, OPTIND évolue au fil du traitement et s'incrémente séquentiellement correspondant au numéro du paramètre actuellement analysé. C'est donc un simple nombre. Dans notre séquence, arrivé à « "oui - non.txt" », il vaut 3.
Pour ruser, je dis FILE="${!OPTIND}", ce qui est une référence indirecte à la valeur de OPTIND, soit le paramètre positionnel 3, « $3 ». C'est à dire le nom du fichier. En gros bash va lire « FILE="$3" ».
Comme vu précédemment, getopts va alors croire que les options sont terminées, il faut donc incrémenter encore une fois OPTIND pour qu'il continue d'analyser non pas à partir de « "oui - non.txt" », mais à partir de l'option suivante « -n », et puisse donc traiter des options postérieures à une option longue avec argument « --test arg ». C'est pourquoi intervient :
let "OPTIND += 1"
Qu'il faut rajouter, par conséquent, dans le traitement de toute option longue ayant un argument.
Du coup, une option longue est plus souple avec ce système qu'une option courte normale, car elle peut avoir plusieurs arguments ! (il suffit d'incrémenter OPTIND du nombre d'arguments donnés à l'option longue).
J'espère que ça te semble plus clair (pas sur de mon coup là mais bon :s )
Dernière modification par FRUiT (Le 22/06/2011, à 19:19)
Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean
Hors ligne
#11 Le 22/06/2011, à 18:54
- Hizoka
Re : [résolu?] [bash] - getopts
franchement, merci beaucoup !
c'est bien plus clair !
je connaissais le coup du ${!var} en plus, je l'utilise dans certains scripts...
en tout cas, c'est bien dommage de devoir faire tout ça pour que ca soit fonctionnel.
Merci beaucoup à toi !!
KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github
Hors ligne
#12 Le 22/06/2011, à 19:07
- FRUiT
Re : [résolu?] [bash] - getopts
De rian avec plaisir ^^
Neon Suite by FRUiT (kde4.6) [url]http://[Merci de relire les règles]/yzm7cee[/url]
"Pour la carotte, le lapin est la plus parfaite incarnation du mal" (R. Sheckley)
clean
Hors ligne
Pages : 1