IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Gestion des arguments


Sujet :

Shell et commandes GNU

  1. #1
    Membre confirmé
    Inscrit en
    Juillet 2006
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 66
    Par défaut Gestion des arguments
    Bonjour,

    J'ai un shell script tel que :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    USAGE : `basename $0` [-VhD] | [xyz] | [all]
    Indépendamment des arguments traditionnels Version, Help et Debug, je souhaite pouvoir passer des arguments au format "xyz" (j'ai une quinzaine de possibilités différentes mais je n'en passe qu'une seule à la fois) dont une générique "all".

    J'ai bien pensé à utiliser "getopts", ce qui ne pose pas de problème pour les arguments "-V, -h et -D" mais qui ne fonctionne plus si je passe simplement une valeur de type "xyz".
    Du coup, quelle serait selon vous la meilleure méthode pour traiter ces arguments "disparates" ?

    Un exemple serait apprécié

    Merci de vos réponses
    Cordialement
    oracle7556

  2. #2
    Membre chevronné
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 563
    Par défaut
    Salut,

    Perso j'utilise ce genre de code plus modulable que getops.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    while [[ ${*} ]]
    do
        if (( ! StopArg ))
        then
            case "${1,,}" in
                "--") StopArg=1 ;;
     
                --option1|-o) ...
     
                --option2)
                    # Récupération d'une possible valeur, celle ci ne soit pas commencer par un -
                    # attention a ne pas mettre une option avec valeur facultative avant tes valeurs hors arguments sinon il pensera que ça en fait parti
                    [[ ${2} != -* ]] && { Valeur="${2}"; shift; }
                    ...
     
                -[a-zA-Z]*) argument inconnu mais pourquoi ne pas s'amuser à décortiquer les caractères 1 à 1, ce sont peut être des options courtes que tu peux traiter via une boucle.
     
                *) valeur hors argument
            esac
     
       else
          echo "ce ne sont plus que des valeurs hors arguments car -- a été utilisé"
       fi
     
       unset Valeur
       shift
    done

  3. #3
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 298
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 298
    Par défaut
    Bonjour

    mais qui ne fonctionne plus
    Que veut dire cette phrase ? Qu'est-ce qui ne fonctionne plus ?

    Je vois bien un message, une démarche, mais je ne vois pas d'obstacle qui demande notre concours.

  4. #4
    Membre confirmé
    Inscrit en
    Juillet 2006
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 66
    Par défaut
    @Flodelarab

    Bonjour,

    Je précise que je débute aussi SVP soyez indulgent ... Ce n'est pas facile pour moi cette syntaxe ...

    Avec une gestion sous getopts j'arrive à traiter les arguments -V, -h et -D mais si je fais ceci : ./monscript.sh xyz , je n'ai pas de traitement correspondant.
    J'ai essayé de décoder l'argument avec une expression régulière et puis directement avec une chaine en "dur", mais cela ne marche pas. J'ai raté un truc ?

    Merci de BV m'expliquer SVP.

    Mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    while getopts ":VhD" opt
    do
      case $opt in
      V | --version)
        voir_version
        ;;
      h | --help)
        usage
        ;;
      D | --debug)
        (( DEBUG++ ))
        ;;
      "^[a-z]{3}$")
        echo "expR - "$opt
        ;;
      xyz)
        echo "xyz - "$opt
        ;;
      *)
        echo "Argument inconnu: -$OPTARG" >&2
        usage
        exit $EX_ERR_GEN
        ;;
      esac
    done
    @hizoka

    Merci pour ton exemple, même si je ne comprends pas toutes les actions, je vais creuser.

    Cordialement
    oracle7556

  5. #5
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 298
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 298
    Par défaut
    J'ai raté un truc ?
    Oui. Tu as raté qu'une option commence par un ou deux tirets. xyz est donc un argument de ta commande.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    shift "$((OPTIND-1))"
    monpremierargument=$1
    monsecondargument=$2
    echo "$monpremierargument $monsecondargument"
    En écrivant ce code à la suite de ta boucle "getopts", tu verras que ton premier argument est "xyz".
    Libre à toi de boucler sur les arguments aussi. Et de détecter "all" pour un traitement particulier.

    De ce que je comprends, tu as certainement envie d'utiliser les valeurs $@ et $*. Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for i in "$@";do echo $i;done
    for i in "$*";do echo $i;done
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ ./test.bash toto tata titi
    toto
    tata
    titi
    toto tata titi
    Il a fait la première boucle pour chacun, puis la deuxième boucle pour tous. Pour en savoir plus sur les paramètres spéciaux, tape (ou copie-colle) ceci (q pour quitter):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    man -P 'less -p"^ +Paramètres spéciaux"' bash

  6. #6
    Membre confirmé
    Inscrit en
    Juillet 2006
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 66
    Par défaut
    @FLodelarab

    Bonjour,

    Désolé pour le retard à répondre, j'étais plongé dans mon truc ..

    Donc merci pour l'astuce du shift.

    Finalement voici mon code qui répondait à ma question initiale.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    #
        # ---- On sauvegarde le Nombre de paramètres passés au script
    nbparam=$#
     
    if [[ $nbparam -gt 1 ]]
      then
            # ---- Erreur, il y a trop d'arguments passés (0 ou 1 maxi)
        erreur 1 "Trop d'arguments (Nb=$nbparam) ont ete passes au shell script '$NOMPROG'"
        exit $EX_ERR_GEN
    fi
    if [[ $nbparam -gt 0 ]]
      then
      #-----------------------------------------------------
      # On interprete l'argument passé à la commande 'livebox.sh'
      #-----------------------------------------------------
      while getopts ":VhD-:" opt "$@"
      do
            # ---- On convertit les arguments longs en arguments courts
        [[ $opt = "-" ]] && case $OPTARG in
            version) opt=V ;;
            help) opt=h ;;
            debug) opt=D ;;
        esac
            # ---- On traite les arguments courts
        case $opt in
          V)
            voirVersion
            ;;
          h)
            usage
            ;;
          D)
            (( DEBUG++ ))
            ;;
          *)
            # echo "Argument inconnu: -$OPTARG" >&2
            erreur 1 "'-$OPTARG' -- Valeur d'argument inconnue !"
            exit $EX_ARG_INCONNU
            ;;
        esac
      done
      shift "$((OPTIND-1))"
      #-----------------------------------------------------
      # On traite l'argument standard (domaine) si renseigné
      #-----------------------------------------------------
          # ---- On vérifie que le domaine existe bien
      if [[ ! $(printf "_[%s]_" "${lst_trigram[@]}") =~ .*_\[$1\]_.* ]]
        then
          # Le domaine n'est pas référencé : on sort
          erreur 1 "'$1' -- Valeur d'argument inconnue !"
          exit $EX_ARG_INCONNU
      fi
          # ---- On sauve le domaine pour lequel les données extraites sont à afficher
      domaine=$1
    fi
    Cordialement
    oracle7556

  7. #7
    Membre chevronné
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 563
    Par défaut
    Je pige pas trop, si tu n'autorise qu'une seule option, t’embête pas avec getops fais juste un case sur "$1"...

  8. #8
    Membre chevronné
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 563
    Par défaut
    Pour le fun, je suis allé plus loin dans ce que je m'étais créé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    unset StopOptions
    while [[ ${*} ]]
    do
        # Options indiquant que la suite ne contient plus d'option
        # Avec ce système, on peut utiliser -- comme argument : commande ... -- dqsdsq -- dsqdsq => le 2e -- est un argument et non à nouveau un indicateur d’arrêt des options
        if [[ -z ${StopOptions} && "${1}" == "--" ]] 
        then
            StopOptions=1
            shift
            continue
        fi
     
        # Si on a pas indiqué que les options sont terminées
        if (( ! StopOptions ))
        then
            unset Options Temp
     
            # Si c'est une option longue
            if [[ "${1}" == "--"* ]]
            then
                Options=("${1/#--}")
     
            # Si c'est une option courte ou plusieurs options courtes concaténées
            elif [[ "${1}" == "-"* ]]
            then
                Temp="${1/#-}"
                [[ ${Temp} =~ ${Temp//?/(.)} ]] && Options=("${BASH_REMATCH[@]:1}")
     
            # Si c'est un argument
            else
                echo "${1} est un argument"
            fi
     
            # Traitement des options
            for Option in "${Options[@]}"
            do
                case "${Option}" in
                    h|help) echo "Help me !" ;;
     
                    a|all) echo "option all" ;;
     
                    s|special) 
                        # Si cette option nécessite une valeur, on la recherche
                        # Cette option doit être la dernière de la liste car elle attend une valeur
                        if [[ "${Option}" != "${Options[-1]}" || "${2-vide}" == "vide" ]]
                        then
                            echo "l'option ${Option} nécessite une valeur !"
     
                        else
                            # Récupération de la valeur même vide
                            ValeurOption="${2}"
     
                            # On déplace les arguments d'1
                            shift
     
                            echo "L'option ${Option} a pour valeur ${ValeurOption}"
                        fi ;;
     
                    *) echo "${Option} n'est pas une option valide !";;
                esac
            done
     
        # Si ce ne sont plus des options, ce sont des arguments
        else
            echo "${1} est un argument post --"
        fi
     
        # On déplace les arguments d'1
        shift
    done
    Normalement, je n'ai rien oublié

    commande -azerty comprend les options courtes -a -z -e -r -t -y
    commande --azerty comprend l'option longue azerty
    commande azerty comprend l'argument azerty
    commande -azerty -- -azerty comprend les options courtes -a -z -e -r -t -y puis l'argument -azerty
    commande -azertys "blabla" comprend les options courtes -a -z -e -r -t -y et -s avec pour valeur blabla

    La seule question est comment réagir face à ça : commande --special --
    Doit on comprendre -- comme étant la valeur de l'option special ou doit il indiqué la fin des options et afficher une erreur car l'option special n'a pas eu sa valeur...
    Actuellement, il la comprend comme une valeur.

  9. #9
    Membre confirmé
    Inscrit en
    Juillet 2006
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Juillet 2006
    Messages : 66
    Par défaut
    Bonjour,

    Je croyais que mon bout de code donné dans ma précédente réponse fonctionnait. Eh bien non !

    Tel qu'il est, en essayant de mettre en place ma fonction de debug et donc en utilisant les options "-D" ou "--debug" je récupère le message suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Erreur : '' -- Valeur d'argument inconnue !
    USAGE : livebox.sh [-hDV] | [xyz] | [all]
    Pouvez-vous SVP m'aider à comprendre mon erreur ? Qu'est-ce qui cloche dans le code ?
    Merci d'avance.

    Cordialement
    oracle7556

  10. #10
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 694
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 694
    Par défaut
    Citation Envoyé par man bash /getopts
    si un caractère est suivi par un deux-points, l'option est censée avoir un argument, qui devrait en être séparé par une espace.
    il existe une commande externe getopt qui gère aussi les options longues.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  11. #11
    Membre chevronné
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2013
    Messages : 563
    Par défaut
    Teste ma proposition, ça prend tout en compte normalement.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/02/2011, 18h03
  2. Gestion efficasse des arguments
    Par mamax29 dans le forum Langage
    Réponses: 11
    Dernier message: 17/05/2010, 12h52
  3. Gros souci avec gestion des arguments
    Par toams69 dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 0
    Dernier message: 09/01/2009, 17h59
  4. gestion propre des arguments du main
    Par jobherzt dans le forum C++
    Réponses: 1
    Dernier message: 30/08/2006, 19h17
  5. c: gestion des exceptions
    Par vince_lille dans le forum C
    Réponses: 7
    Dernier message: 05/06/2002, 15h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo