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 :

Comprendre if &&


Sujet :

Shell et commandes GNU

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 142
    Par défaut Comprendre if &&
    Bonjour

    Je me trouve confronter à problème de syntaxe/incompréhension. le code ci-dessous fonctionne mais pas exactement comme je le veux. Dans la déclaration du if, je cherche a faire un &&. Cela marche mais le shell fait comme si "&& $i != $expr" était quelque chose a éxéctuer et me retourne un message du type : valeur de $i : Permission denied ...

    A ce stade, $i est un chemin. Je veux simplement qu'il vérifie si $i est différents de $expr. Mais il m'écoute pas, il fait ce que je lui dit, pas ce que je veux ... ^^

    Quelqu'un pourrait m'aider à comprendre cette $$@#! de syntaxe ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     if ( ! echo ${tab_exeption[*]} | grep -q $i &&  $i != $expr ) ; then
        gpg --verify $i $strmod"Release" &>/dev/null
        if [ $? != 0 ] ; then
          error=1
          tab_error[$vartab]=$i
          ((vartab++))
        fi
      fi

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Il y a plein de façon de faire, en voilà une :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ( ! echo ${tab_exeption[*]} | grep -q $i &&  [ $i != $expr ] )

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 142
    Par défaut
    Citation Envoyé par matafan Voir le message
    Il y a plein de façon de faire, en voilà une :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ( ! echo ${tab_exeption[*]} | grep -q $i &&  [ $i != $expr ] )
    Merci,

    Mais pourrais-tu m'expliquer ce qui colle pas dans mon truc ?

    De plus, maintenant je me rend compte qu'en fait mon code ne fonctionne pas.

    En toute logique, je voudrais m'assurer que $i ne commence pas par /home. De fait, j'ai initialisé la variable expr à : ^/home/ . Et bien évidemment, ca ne fonctionne pas !

    Bon en tout cas, la modif proposé fonctionne, c'est déjà une erreur de moins !

    Merci

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 142
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ( ! echo ${tab_exeption[*]} | grep -q $i && [[ $i =~ $expr ]] )
    A réglé mon problème de regex.

  5. #5
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 103
    Par défaut
    Citation Envoyé par Nelmo Voir le message
    Merci,
    Mais pourrais-tu m'expliquer ce qui colle pas dans mon truc ?
    Bonjour,
    dans la ligne que tu as indiquée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if ( ! echo ${tab_exeption[*]} | grep -q $i &&  $i != $expr ) ; then
      blabla
    fi
    Les parenthèses ne servent à rien: elles ne font que générer un sous-shell inutile. Ce code est donc équivalent à quelque chose comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if cmd1 &&  $i != $expr ; then
      blabla
    fi
    Le shell, lisant de gauche à droite, exécute cmd1 puis, si le résultat est vrai (ou $? == 0), il exécute la suite qui est $i != $expr. Il expanse $i puis considère son résultat comme le nom d'une commande à exécuter, ce qui n'est évidemment pas ce que tu souhaites, et va te sortir un joli message d'erreur, par exemple, si le contenu de $i est "coucou":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ksh: coucou:  not found.
    Manifestement, tu voudrais tester si $i est différent de $expr. Pour cela, il faut exécuter un programme de test, par exemple la commande interne du shell test, soit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if cmd1 &&  test $i != $expr ; then
      blabla
    fi
    qui va faire ce que tu voulais.

    Il existe une autre commande de test. C'est la commande interne du shell [:

    et qui, à ma connaissance, ne fait guère plus que d'appeler test, soit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if cmd1 &&  [ $i != $expr ]; then
      blabla
    fi
    Du coup, on comprend aussi pour quoi il faut absolument une espace avant et après [. Sinon il cherche la commande [$i.

    Ces 2 commandes ont leur équivalent en programme externe ici:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ ls -l '/usr/bin/[' /usr/bin/test
    -rwxr-xr-x 1 root root 30064 Oct 30  2008 /usr/bin/test*
    -rwxr-xr-x 1 root root 32296 Oct 30  2008 /usr/bin/[*
    Une autre possibilité est d'utiliser une autre fonction de comparaison interne au shell:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if cmd1 &&  [[ $i != $expr ]]; then
      blabla
    fi
    Voilà.
    HTH
    )jack(

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 662
    Par défaut
    Bonjour,

    Citation Envoyé par jack-ft
    Une autre possibilité est d'utiliser la fonction de comparaison interne au shell:
    test et [ sont aussi des commandes internes du shell !
    Il y a de nombreuses commandes internes du shell qui ont leur homonyme sous /bin/.
    Si on n'utilise pas les propriétés avancées de [[, autant utiliser test, ou [.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  7. #7
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 103
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    Bonjour,

    test et [ sont aussi des commandes internes du shell !
    Il y a de nombreuses commandes internes du shell qui ont leur homonyme sous /bin/.
    Si on n'utilise pas les propriétés avancées de [[, autant utiliser test, ou [.
    Bonjour,
    je viens de vérifier et j'apprends(!) je confirme que test et [ sont aussi des commandes internes du shell !

    Pour tester "test", il suffit par exemple de faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ echo "echo coucou" > ./test
    $ chmod +x ./test
    $ PATH=.:$PATH
    $ test 3 = 4
    $ echo $?
    1
    Du coup, je vais corriger mon précédent post pour éviter de laisser des informations erronées qui pourraient enduire d'erreur les lecteurs potentiels!

    Par ailleurs, le livre "Le KornShell" de Bolsky et Korn (de 1989-1990), à la page 352, au paragraphe "Caractéristiques obsolètes", indique:
    Attention: les caractéristiques suivantes sont actuellement supportées par ksh uniquement dans un but de compatibilité. Leur utilisation est fortement déconseillée. Ces caractéristiques pourront être supprimées dans le futur:
    - Les options -k et -t de set.
    - echo comme commande intégrée. (utilisez plutôt print).
    - test et [ comme commandes intégrées. (utilisez plutôt [[...]]).
    - La substitution de commande `...`. (utilisez plutôt $(...)).
    - La syntaxe de définition de fonction identificateur(). (utilisez plutôt function identificateur).

    Qu'en pensent nos spécialistes?

    )jack(

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 662
    Par défaut
    = effectue une comparaison lexicale (tout comme >, et <).
    Pour effectuer une comparaison arithmétique (tester si un nombre est égal à un autre, supérieur (ou égal), inférieur (ou égal)), il existe des opérateurs arithmétiques :
    -eq égal (equal)
    -ne n'est pas égal à (not equal)
    -gt strictement supérieur (greater than)
    -ge supérieur ou égal (greater or equal)
    -lt strictement inférieur (lesser than)
    -le inférieur ou égal (lesser or equal)

    ou alors on utilise l'évaluation arithmétique entre double parenthèses :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    (( nombre1 = nombre2 ))
    (( nombre1 != nombre2 ))
    (( nombre1 > nombre2 ))
    (( nombre1 >= nombre2 ))
    (( nombre1 < nombre2 ))
    (( nombre1 <= nombre2 ))
    le signe dollar des variables n'est pas nécessaire dans ce cas.

    "Le KornShell" de Bolsky et Korn (de 1989-1990)
    j'en pense que depuis plus de vingt ans après echo et [ sont toujours là.
    $( ) a effectivement supplanté ` `
    function n'est pas POSIX.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 142
    Par défaut
    Merci pour vos explications, je lis tout ça et reviens vous.

    Edit : Je vous remercie pour ces explications, c'est très intéressant ! Un post que je vais garder dans mes favoris

  10. #10
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 838
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 838
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par jack-ft Voir le message
    - echo comme commande intégrée. (utilisez plutôt print).
    Bonjour
    Soit il y a une erreur dans le bouquin, soit la phrase a été mal retranscrite ici car il n'y a aucun rapport entre print (qui est une commande associée à mailcap) et echo. A mon avis, c'est plutôt de printf qu'il parlait...
    Maintenant echo est une primitive du shell mais au cas où celle-ci disparaitrait (???), il reste toujours la commande /bin/echo...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  11. #11
    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
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Soit il y a une erreur dans le bouquin, soit la phrase a été mal retranscrite ici car il n'y a aucun rapport entre print (qui est une commande associée à mailcap) et echo. A mon avis, c'est plutôt de printf qu'il parlait...
    Pas d'erreur car il ne s'agit pas du print de mailcap. C'est ici de la commande interne print de ksh qu'il s'agit. Il vaut mieux utiliser que la commande echo qui pose problème en raison d'implémentations incompatibles entre les différents Unix (à l'origine entre BSD & System V). Cela dit, printf est une meilleure alternative puisque standard.
    Maintenant echo est une primitive du shell mais au cas où celle-ci disparaitrait (???), il reste toujours la commande /bin/echo...
    Peu de risque qu'echo disparaisse comme primitive shell. Ça n'aurait aucun sens.

  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
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    $( ) a effectivement supplanté ` `
    Les deux syntaxes sont sont toujours supportées mais $( ) est bien sûr préférable.
    function n'est pas POSIX.
    mais est toujours recommandée dans des scripts ksh car elle présente des caractéristiques nettement plus intéressantes que la syntaxe standard:
    • affectation de $0
    • support des variables locales
    • OPTIND (getopts) spécifique par fonction
    • meilleure gestion des traps, signaux, exceptions

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

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