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 :

[bash]Modification de paramètres dans une boucle


Sujet :

Shell et commandes GNU

  1. #1
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 598
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 598
    Points : 7 837
    Points
    7 837
    Par défaut [bash]Modification de paramètres dans une boucle
    Bonjour

    Je ne vois pas pourquoi le passage dans ma boucle grep "/media/" /etc/mtab | grep -v floppy | grep -v cdrom | while read LINE ; do ne modifie pas les valeurs de mes paramètres !
    Ou plutôt, pourquoi les modifications de mes paramètres ne sont pas retenues.

    On voit bien qu'ils sont affectés, mais en fin de boucle on retrouve les valeurs d'avant !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    drap=1
     
    echo "drap=$drap => $mes"
     
    grep "/media/" /etc/mtab | grep -v floppy | grep -v cdrom | while read LINE ; do
     drap=`echo $(($drap+1))`
     mes=$(echo "$mes \n$LINE")
     echo "drap=$drap => $mes"
    done
     
    echo "drap=$drap => $mes"
    donne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    drap=1 => 1 clef(s) rajoutée(s)
    drap=2 => 1 clef(s) rajoutée(s) \n/dev/sdd1 /media/h2 vfat rw,nosuid,nodev,sync,users,umask=0022,iocharset=utf8 0 0
    drap=1 => 1 clef(s) rajoutée(s)

  2. #2
    LLB
    LLB est déconnecté
    Membre expérimenté
    Inscrit en
    Mars 2002
    Messages
    967
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 967
    Points : 1 410
    Points
    1 410
    Par défaut
    Parce que le pipe crée un nouveau processus (par fork). C'est donc un processus fils qui exécute la boucle while. Les variables modifiées ne sont donc pas reportées au père.

    Tu peux faire un mkfifo, rediriger la sortie dans le tube nommé et lire les infos dans le processus père.

    Je ne sais pas s'il y a plus simple.

  3. #3
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 598
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 598
    Points : 7 837
    Points
    7 837
    Par défaut
    man mkfifo est très peu parlant ! J'aurais besoin d'un exemple pour comprendre.

  4. #4
    Membre éclairé Avatar de BlaireauOne
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    492
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2007
    Messages : 492
    Points : 652
    Points
    652
    Par défaut
    Ça doit le faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    drap=1
    echo "drap=$drap => $mes"
    mkfifo PipeLine
    grep "/media/" /etc/mtab | grep -E -v "(floppy|cdrom)" > PipeLine &
    while read LINE ; do
      ((drap=drap+1))
      mes=$(echo "$mes \n$LINE")
      echo "drap=$drap => $mes"
    done < PipeLine
    echo "drap=$drap => $mes"
    rm PipeLine

  5. #5
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 598
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 598
    Points : 7 837
    Points
    7 837
    Par défaut
    Ça marche !

    Il me reste à comprendre...


  6. #6
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 598
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 598
    Points : 7 837
    Points
    7 837
    Par défaut
    À tester :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/bin/bash
    [...]
    drap=1
     
    while read line; do
    	drap=$((drap+1))
    	mes="$mes \n$line"
            echo "$line"
    done < <(grep "/media/" /etc/mtab | grep -v floppy | grep -v cdrom)
     
    echo $drap

  7. #7
    LLB
    LLB est déconnecté
    Membre expérimenté
    Inscrit en
    Mars 2002
    Messages
    967
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 967
    Points : 1 410
    Points
    1 410
    Par défaut
    Oui, pas mal. La notation <( ) crée un file descriptor temporaire.
    C'est donc la même logique qu'avec mkfifo, c'est plus joli, mais moins portable (ce n'est pas posix).

  8. #8
    Membre éclairé Avatar de BlaireauOne
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    492
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2007
    Messages : 492
    Points : 652
    Points
    652
    Par défaut
    Autre solution

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    drap=1
    echo "drap=$drap => $mes"
    for LINE in $(grep "/media/" /etc/mtab | grep -E -v "(floppy|cdrom)") ; do
      ((drap=drap+1))
      mes=$(echo "$mes \n$LINE")
      echo "drap=$drap => $mes"
    done 
    echo "drap=$drap => $mes"

  9. #9
    LLB
    LLB est déconnecté
    Membre expérimenté
    Inscrit en
    Mars 2002
    Messages
    967
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 967
    Points : 1 410
    Points
    1 410
    Par défaut
    Oui, mais c'est assez différent : tout le contenu de la commande est stocké en mémoire avant d'exécuter la boucle. Sur un flux très long, c'est à déconseiller. Si l'entrée correspond au clavier, le comportement sera différent (non interactif).

    Mais si la commande renvoie peu de résultats, c'est en effet une bonne alternative.

  10. #10
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 598
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 598
    Points : 7 837
    Points
    7 837
    Par défaut
    Je comprends mieux cette méthode qui me montre en plus comment utiliser un grep -v avec 2 mots à virer.
    C'était une question que je me posait depuis longtemps ! En plus, elle doit aussi marcher pour sélectionner les lignes qui contiennent soit un mot, soit l'autre : encore mieux que prévu !

  11. #11
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 598
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 598
    Points : 7 837
    Points
    7 837
    Par défaut
    Je corrige :
    Citation Envoyé par BlaireauOne Voir le message
    Autre solution

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    drap=1
    echo "drap=$drap => $mes"
    for LINE in "$(grep "/media/" /etc/mtab | grep -E -v "(floppy|cdrom)")" ; do
      ((drap=drap+1))
      mes=$(echo "$mes \n$LINE")
      echo "drap=$drap => $mes"
    done 
    echo "drap=$drap => $mes"
    En effet, mes lignes contiennent plusieurs paramètres, donc je maintiens leur unité avec les ".

  12. #12
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 598
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 598
    Points : 7 837
    Points
    7 837
    Par défaut
    Et bien, ça ne marche pas non plus... Ça concatène la sortie en un seul bloc... Il faudrait concaténer uniquement les lignes. Et, là, pas d'idée !

  13. #13
    LLB
    LLB est déconnecté
    Membre expérimenté
    Inscrit en
    Mars 2002
    Messages
    967
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 967
    Points : 1 410
    Points
    1 410
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    IFS="
    "
    for LINE in $(grep "/media/" /etc/mtab | grep -E -v "(floppy|cdrom)") ; do

  14. #14
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 598
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 598
    Points : 7 837
    Points
    7 837
    Par défaut
    C'est quoi ce :
    IFS="
    "


    Qu'est-ce qu'il fait au juste ? Un man ne dit rien !

  15. #15
    LLB
    LLB est déconnecté
    Membre expérimenté
    Inscrit en
    Mars 2002
    Messages
    967
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 967
    Points : 1 410
    Points
    1 410
    Par défaut
    Si, c'est expliqué dans le man (bash).

    IFS = Internal Field Separator. Ca indique au shell comment découper les tokens. Par défaut, il utilise l'espace, la tabulation et le retour ligne. Ma ligne indique que le seul séparateur de mots est le retour ligne.

  16. #16
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 598
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 598
    Points : 7 837
    Points
    7 837
    Par défaut
    Très fort ! Mais après l'utilisation de cet artifice, on doit le remettre comme avant ! Et là, le man bash n'est pas très parlant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
           IFS    The Internal Field Separator that is used for word splitting after expansion and to  split  lines  into  words  with  the  read
                  builtin command.  The default value is ‘‘<space><tab><newline>''.

  17. #17
    LLB
    LLB est déconnecté
    Membre expérimenté
    Inscrit en
    Mars 2002
    Messages
    967
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 967
    Points : 1 410
    Points
    1 410
    Par défaut
    En général, non.
    Ton script étant exécuté dans un sous-shell, la modification de l'IFS n'est pas censée être répercutée en dehors. Si tu veux le restaurer pour la suite de ton script, c'est pas compliqué :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    IFS_OLD="$IFS"
    ...
    IFS="$IFS_OLD"
    Et le man est parlant : il te donne la valeur par défaut (espace - tabulation - retour ligne).

  18. #18
    Rédacteur/Modérateur
    Avatar de troumad
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2003
    Messages
    5 598
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 5 598
    Points : 7 837
    Points
    7 837
    Par défaut
    J'avais vu, mais je ne voyais pas comment générer moi même cet ancien IFS. C'est vrai qu'il suffisait de le mémoriser !

    J'en aurais appris des choses
    Et ma correction de copies n'avance pas
    C'est ma femme qui va raller !

    beaucoup !

  19. #19
    LLB
    LLB est déconnecté
    Membre expérimenté
    Inscrit en
    Mars 2002
    Messages
    967
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 967
    Points : 1 410
    Points
    1 410
    Par défaut
    Voilà !

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

Discussions similaires

  1. sub avec paramétre dans une boucle
    Par gastoncs dans le forum VB.NET
    Réponses: 1
    Dernier message: 23/12/2011, 14h58
  2. Objet paramétré dans une boucle
    Par CedricMoi dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 05/02/2009, 10h21
  3. pause de durée paramètrable dans une boucle
    Par atomicJo dans le forum C++
    Réponses: 14
    Dernier message: 12/11/2007, 23h06
  4. Pb de modification de liste dans une boucle for
    Par schnito dans le forum Général Python
    Réponses: 5
    Dernier message: 20/04/2007, 10h27
  5. Réponses: 3
    Dernier message: 01/09/2005, 11h56

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