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 :

Utilisation du getopts dans une fonction (Bash/ksh)


Sujet :

Shell et commandes GNU

  1. #1
    Candidat au Club
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Novembre 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Service public

    Informations forums :
    Inscription : Novembre 2014
    Messages : 6
    Points : 3
    Points
    3
    Par défaut Utilisation du getopts dans une fonction (Bash/ksh)
    Bonjour à tous,

    Je viens de m’apercevoir que si j'utilise une deuxième fois la même fonction (avec des paramètres lus par getopts) dans un même script, la seconde exécution de la fonction ne lit pas les paramètres. Si je remplace le getopts par une lecture des paramètres avec $1, $2, ... ça fonctionne... Ouf, je ne suis pas fou...

    Savez-vous pourquoi ou comment résoudre ce soucis ?

    Je me monte une bibliothèque de fonction pour réécrire une p'tite appli et l'utilisation du getopts dans les fonctions m'aide énormément.

    Voici mon script :
    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
    #!/bin/ksh
    calculdate() {
    # Calcule une date à plus ou moins n jours
    # 
    # Exemple :
    #   Quelle est la date dans 15 jours (date début = date du jour) ?
    #     calculdate -d 8 (aujourd'hui = 18/05/2015)
    #        --> 26/05/2015
    #   Quelle est la date de demain (date début = date du jour) ?
    #     calculdate (aujourd'hui = 18/05/2015)
    #        --> 19/05/2015
    #   Quelle est la date il y a 7 jour (date début = date du jour) ?
    #     calculdate -d 8 -s moins (aujourd'hui = 18/05/2015)
    #        --> 10/05/2015
    #   Quelle est la date 5 jours après le 30/06/2015 ?
    #     calculdate -j 30 -m 05 -a 2015 -d 5
    #        --> 04/06/2015
      echo debug $# $*  
      typeset -u sens
     
    #  jour=$1
    #  mois=$2
    #  annee=$3
    #  delai=$4
    #  sens=$5
      while getopts :j:m:a:d:s: c
      do
        case $c in
             j)      jour=$OPTARG;;
             m)      mois=$OPTARG;;
             a)      annee=$OPTARG;;
             d)      delai=$OPTARG;;
             s)      sens=$OPTARG;;
             *)      echo "Parametre non connu !!!"
                     echo "calculdate [ -j <JJ> -m <MM> -a <CCAA> ] [ -d <nn> ] [ -s <PLUS|MOIS> ]"
                     return 99;;
        esac
      done
     
      # Initialisation des variables
      test -z $jour && jour=$(date '+%d')
      test -z $mois && mois=$(date '+%m')
      test -z $annee && annee=$(date '+%Y')
      test -z $delai && delai=1
      test -z $sens && sens="PLUS"
      test $sens == "MOINS" && avant="ago" || avant=""
     
      # formatage sur 2 chiffres du jour et du mois
      #jour=$(printf "%02d" $jour)
      #mois=$(printf "%02d" $mois)
      # Calcul de la date voulue
      newdate=$(date -d "$annee-$mois-$jour $delai day $avant" '+%d/%m/%Y')
      # Réponse de la fonction
      echo $newdate
      return 0
    }
    echo "Fonction calculdate :"
    echo "--> Quelle est la date 5 jours après le 30/04/2015 ? (calculdate -j 30 -m 4 -a 2015 -d 5)"
    calculdate -j 30 -m 04 -a 2015 -d 5
    calculdate -j 20 -m 03 -a 2014 -d 4
    exit 0
    Abou33

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 459
    Points
    13 459
    Par défaut
    Bonjour

    Pourquoi tu n'utilises pas date ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ date
    mar. 19 mai 2015 11:08:18
    $ date -d "1 day ago"
    lun. 18 mai 2015 11:09:08
    $ date -d "3 day ago"
    sam. 16 mai 2015 11:09:16
    $ date -d "-3 day ago"
    ven. 22 mai 2015 11:10:38
    $
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  3. #3
    Candidat au Club
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Novembre 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Service public

    Informations forums :
    Inscription : Novembre 2014
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    J'suis d'accord mais ce n'est qu'un exemple de fonction que j'ai mis ici.

    Le soucis est vraiment sur le passage de paramètres avec getopts.

    Merci de ta réponse rapide.

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 459
    Points
    13 459
    Par défaut
    Tu dois rajouter la ligne suivante dans ta fonction juste avant le while:
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  5. #5
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 842
    Points
    7 842
    Par défaut
    Puisque tu utilises ksh, une solution simple consiste à définir ta fonction comme ça:
    plutôt que
    En bash, tu peux déclarer OPTIND comme variable locale à la fonction:
    ɹǝsn *sıɹɐlos*

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    bonjour,

    voir : Fonction avec getopts ne s'exécute qu'une seule fois

    Citation Envoyé par jlliagre
    Puisque tu utilises ksh, une solution simple consiste à définir ta fonction comme ça:
    plutôt que
    euh, mais pourquoi ?
    j'aurais pensé que tu aurais penché pour la version POSIX.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  7. #7
    Candidat au Club
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Novembre 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Service public

    Informations forums :
    Inscription : Novembre 2014
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Merci à tous.

    Je vais prendre le "local OPTIND". Je trouve cette solution propre.

    Abou33.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    sauf qu'un jour, tu n'utiliseras pas getopts dans une fonction, et alors tu devras faire comme j'ai appris, et comme je le préconise.
    autant commencer tout de suite !
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  9. #9
    Candidat au Club
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Novembre 2014
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Service public

    Informations forums :
    Inscription : Novembre 2014
    Messages : 6
    Points : 3
    Points
    3
    Par défaut
    Ne t'inquiètes pas. Je garde toutes les réponses pour en tirer le mieux plus tard.

    Merci
    Abou33

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 459
    Points
    13 459
    Par défaut
    Est-ce que la variable OPTIND peut porter un autre nom ?
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    non. pourquoi ? à quoi tu penses ?
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  12. #12
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 842
    Points
    7 842
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    euh, mais pourquoi ?
    j'aurais pensé que tu aurais penché pour la version POSIX.
    Parce que:

    1: "shift $((OPTIND-1))" ne suffit pas, il faut de toute façon réinitialiser OPTIND, c'est d'ailleurs bien la méthode documentée par POSIX
    2: j'étais pressé d'aller déjeuner donc je n'ai pas argumenté ma réponse ... ;-)
    ɹǝsn *sıɹɐlos*

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    ma question portait sur function funcname plutôt que funcname().
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  14. #14
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 842
    Points
    7 842
    Par défaut
    POSIX ne supporte pas les variables locales à une fonction et l'OP utilise ksh, et puis on n'est pas dans le forum POSIX ... ;-)
    ɹǝsn *sıɹɐlos*

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    ça ne répond pas à mon interrogation : pourquoi l'un plus que l'autre ?
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 459
    Points
    13 459
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    non. pourquoi ? à quoi tu penses ?
    A une banane.

    Mais revenons au sujet:
    Tu sais que tu as parcouru OPTIND options et tu veux revenir en arrière. Tu fais donc calculer à ton script le nombre de marches que tu voudrais qu'il franchisse puis tu fais un shift. Que d'efforts! Alors que tu sais que tu souhaites OPTIND=1 comme je l'ai proposé en message #4.

    Je ne vois pas la plus-value d'utiliser la méthode "shift $((OPTIND-1))" ou "shift $((--OPTIND))" sur la méthode "OPTIND=1".
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  17. #17
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Points : 7 842
    Points
    7 842
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    A une banane.

    Mais revenons au sujet:
    Tu sais que tu as parcouru OPTIND options et tu veux revenir en arrière. Tu fais donc calculer à ton script le nombre de marches que tu voudrais qu'il franchisse puis tu fais un shift. Que d'efforts! Alors que tu sais que tu souhaites OPTIND=1 comme je l'ai proposé en message #4.

    Je ne vois pas la plus-value d'utiliser la méthode "shift $((OPTIND-1))" ou "shift $((--OPTIND))" sur la méthode "OPTIND=1".
    Les deux commandes n'ont rien à voir, "shift $((OPTIND-1))" est nécessaire si l'on souhaite récupérer dans $1, $2, etc.. les arguments subsistants qui ne sont pas des options et leurs paramètres, alors que OPTIND=1 est nécessaire pour refaire un getopts avec de nouveaux arguments.
    ɹǝsn *sıɹɐlos*

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    peut-être pour ça :
    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
    $ cat ./getopts.example 
    #!/bin/bash
    echo $_
    usage() {
       echo "usage : ${0##*/} [OPTION(S)]
    -a     : affiche a
    -b     : affiche b
    -c arg : affiche <arg>" >&2
    }
    (($#)) || {
       echo "pas d'arguments" >&2
       usage
       exit 1
    }
    while getopts :abc:d opt
    do
       case $opt in
          a) echo a;;
          b) echo b;;
          c) echo "argument : $OPTARG";;
          :) echo "grosse err #1 : argument requis absent";;
          \?) echo "grosse err #2 : opt = $opt ; OPTARG = $OPTARG ; OPTIND = $OPTIND";;
          *) echo "err ? : opt = $opt ; OPTARG = $OPTARG ; OPTIND = $OPTIND";;
       esac
    done
    shift $((--OPTIND))
    #OPTIND=1
    echo "reste : $@"
    echo "fini"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ ./getopts.example -a -c bla bla
    ./getopts.example
    a
    argument : bla
    reste : bla
    fini
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #shift $((--OPTIND))
    OPTIND=1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ ./getopts.example -a -c bla bla
    ./getopts.example
    a
    argument : bla
    reste : -a -c bla bla
    fini
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

Discussions similaires

  1. Utiliser un string dans une fonction de setInterval
    Par strat0 dans le forum Général JavaScript
    Réponses: 17
    Dernier message: 02/08/2007, 17h56
  2. [SQL SERVER 2005] Utilisation de Exec dans une fonction ?
    Par Dadou74 dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 22/09/2006, 22h09
  3. Utilisation de fstream dans une fonction
    Par Silverstone dans le forum SL & STL
    Réponses: 7
    Dernier message: 22/07/2006, 09h55
  4. utilisation de getdate() dans une fonction ?
    Par devdev dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 08/03/2005, 17h40
  5. Utilisation de Getdate dans une fonction
    Par BaronSamdi dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 16/11/2004, 10h12

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