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 :

Comparer deux tableaux avec des for imbriqués, dur dur..


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 132
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut Comparer deux tableaux avec des for imbriqués, dur dur..
    Bonjour,

    je tombe sur un os et ne sais pas comment le ronger...

    J'ai besoin de récupérer les données de proc/partitions toutes les secondes et ça, je sais faire, mais c'est pour les comparer que je coince.

    J'ai vu/lu plein de tutos, de posts, etc., et je me plante lamentablement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    IFS='\n'
    listenow=$(cat /proc/partitions | grep sd) 
    listeprv="$listenow"
    declare -a newdevice
     
    for lignen in $listenow; do 
      for lignep in $listeprv; do 
        outnow=$(echo $lignen | awk '{print $4}');
        echo $outnow
        outprv=$(echo $lignep | awk '{print $4}'); 
        echo $outprv
        if [ "$outprv" != "$outnow" ]; then echo "outnow = " ; echo "$outnow"; newdevice+=("$outnow"); fi 
      done
    done
    Je n'ai pas tout mis, juste ce qui coince. Et voilà ce que j'obtiens :
    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
    sda
    sda1
    sda2
    sdb
    sdb1
    sdb2
    sdc
    sdc1
    sdc2
    sdd
    sdd1
    <espace rajouté par moi pour séparer *ici* la sortie outnow de la sortie outprv
    sda
    sda1
    sda2
    sdb
    sdb1
    sdb2
    sdc
    sdc1
    sdc2
    outnow =
    Donc en gros je ne peux pas comparer les lignes de l'array listenow avec les lignes de l'array listeprv.

    Je m'attendais à avoir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    sda #venant de listenow
    sda #venant de listeprv
    sda1 #id.
    sda1 #id.
    #etc., jusqu'à 
    sdc2
    sdc2
    sdd
    sdd1
    C'est ces 2 dernières lignes qui m'intéressent (insertion d'une clé usb) et y a pas moyen.

    J'ai même tenté de rajouter des echo pour voir où ça foire, comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for lignen in ${listenow[@]}; do
      echo $lignen 
      for lignep in ${listeprv[@]}; do 
        echo $lignep
    mais ça ne m'avance à rien, voilà la sortie :
    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
       8        0  234431064 sda
       8        1  204800000 sda1
       8        2   29627488 sda2
       8       16 1953514584 sdb
       8       17 1748713472 sdb1
       8       18  204800000 sdb2
       8       32 1953514584 sdc
       8       33 1748713472 sdc1
       8       34  204800000 sdc2
       8       48   30310400 sdd
       8       49   30310160 sdd1
    # dessus la listenow, dessous la listeprv, comme si les boucles n'étaient pas imbriquées, :koi:
       8        0  234431064 sda
       8        1  204800000 sda1
       8        2   29627488 sda2
       8       16 1953514584 sdb
       8       17 1748713472 sdb1
       8       18  204800000 sdb2
       8       32 1953514584 sdc
       8       33 1748713472 sdc1
       8       34  204800000 sdc2
    J'ai raté une marche ?
    Merci,

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

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

    Perso, je laisserais sous forme de fichiers. Et j'utiliserais comm. Il fait 3 colonnes, la colonne du fichier 1, celle du fichier 2, et la 3ème colonne des lignes communes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $ comm <(sort outnow.txt) <(sort outprv.txt)
            outnow =
                    sda
                    sda1
                    sda2
                    sdb
                    sdb1
                    sdb2
                    sdc
                    sdc1
                    sdc2
    sdd
    sdd1
    Mais tu vas me dire que comm travaille sur des fichiers triés, et tu n'as pas besoin de trier les fichiers dans l'absolu. Trop de temps perdu. Alors, tu peux faire la même chose avec awk. La fameuse structure qui prend le premier fichier en référence, le second en traitement. '(FNR==NR){next;} {}'.
    Tu veux les comparer pour sortir quoi ?

  3. #3
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 132
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Tu veux les comparer pour sortir quoi ?
    Détection de l'insertion d'une clé usb (pour test) ou d'un dd externe, pour valider la sauvegarde aussi sur device externe.

    Tiens, première fois que j'entends parler de comm, je vais regarder.


    Sinon, j'avais trouvé un truc qui avait l'air sympa, qui vient d'ici, mais makache bono !
    Citation Envoyé par N_Bah
    en bouclant sur la liste des indices :
    for i in ${!tableau_1[@]}; do echo "${tableau_1[i]} $tableau_2[i]}"; done
    En m'inspirant de cette ligne, j'ai écrit :
    for i in ${!listenow[@]}; do echo "${listenow[i]}" "$listeprv[i]}"; done,
    mais pâté :
    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
       8        0  234431064 sda
       8        1  204800000 sda1
       8        2   29627488 sda2
       8       16 1953514584 sdb
       8       17 1748713472 sdb1
       8       18  204800000 sdb2
       8       32 1953514584 sdc
       8       33 1748713472 sdc1
       8       34  204800000 sdc2
       8       48   30310400 sdd
       8       49   30310160 sdd1    8        0  234431064 sda
       8        1  204800000 sda1
       8        2   29627488 sda2
       8       16 1953514584 sdb
       8       17 1748713472 sdb1
       8       18  204800000 sdb2
       8       32 1953514584 sdc
       8       33 1748713472 sdc1
       8       34  204800000 sdc2[i]}
    D'où sort cette accolade fermante à la fin de la dernière ligne ? Pourquoi y-a-t-il deux lignes combinées en une au milieu de la sortie, quand ça passe d'un tableau à l'autre ?
    Que de soucis que de soucis...

    Et je sais pas pourquoi, je suspecte un pb avec IFS.

  4. #4
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 323
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 323
    Par défaut
    Citation Envoyé par Jipété Voir le message
    En m'inspirant de cette ligne, j'ai écrit :
    for i in ${!listenow[@]}; do echo "${listenow[i]}" "$listeprv[i]}"; done,

    D'où sort cette accolade fermante à la fin de la dernière ligne ?
    Tu ne connais pas bash ? ici, simplement le doigt de N_Bah a "glissé", on ecrit une variable en bash de cette façon : ${variable} (obligatoire avec tableau)

    il manque donc juste le { juste après le $ - Dans ce cas, [i] n'est pas interprété et donc tu n'as pas l'item a l'indice i

  5. #5
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    18 264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 18 264
    Par défaut
    Capilotracté ton truc.

    Tu peux pas regarder le contenu de demsg ? (tu filtre sur le mesg lors du montage de la clé)

    Sinon une ligne comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    grep -v major /proc/partitions | tr -s ' ' | cut -d' ' -f 5 | sort
    te permettra de lister les noms des devices classés alphabétiquement

    Tu peux ensuite appliquer un diff,par raaport à un 1er lancement

    La ligne que j'ai donnée n'est pas forcément optimum mais tu devrais pouvoir la comprendre.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  6. #6
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 132
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Dis donc, c'est pas mal ton truc comm, là !
    Après avoir généré deux fichiers, l'un sans la clé et l'autre avec, hop !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ comm -3 <(sort listenow.lst) <(sort listeprv.lst) | awk '{print $4}'
    sdd
    sdd1


    J'attends de voir ce que les copains de Bash vont proposer.

    Citation Envoyé par chrtophe Voir le message
    Capillotracté ton truc.

    Tu peux pas regarder le contenu de dmesg ? (tu filtres sur le mesg lors du montage de la clé)


    J'y avais pensé mais je me suis dit que des messages système pouvaient s'insérer au milieu, ce qui risquait de devenir compliqué.
    Mais l'utilisation de comm m'a l'air très sympa.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 660
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ prev=( /dev/sd* )
    $ printf '%s\n' "${prev[@]}"
    /dev/sda
    /dev/sda1
    /dev/sda2
    /dev/sda3
    /dev/sda4
    j'insère une clé USB
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ for dev in /dev/sd*; do for i in "${prev[@]}"; do test "$i" = "$dev" && continue 2; done; echo $dev; done
    /dev/sdb
    /dev/sdb1
    ?

    mon doigt a glissé où ?
    on ecrit une variable en bash de cette façon : ${variable}
    quand c'est indispensable uniquement !
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  8. #8
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 132
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Citation Envoyé par papajoker Voir le message
    Tu ne connais pas bash ? ici, simplement le doigt de N_Bah a "glissé", on ecrit une variable en bash de cette façon : ${variable} (obligatoire avec tableau)

    il manque donc juste le { juste après le $ - Dans ce cas, [i] n'est pas interprété et donc tu n'as pas l'item a l'indice i
    Hé bien je n'ai pas vu qu'elle manquait, l'accolade, et la coloration syntaxique de geany ne me l'a pas signalé... Et comme je commence à fatiguer, là, ceci explique cela, d'autant plus qu'en la rajoutant, ça n'a rien changé !

    Citation Envoyé par N_BaH Voir le message
    j'insère une clé USB
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ for dev in /dev/sd*; do for i in "${prev[@]}"; do test "$i" = "$dev" && continue 2; done; echo $dev; done
    Par contre le petit machin de N_Bah ci-dessus m'a l'air hautement sympathique,

    J'ai du test sur la planche, car avec comm ça fonctionne également, le seul souci c'est que je n'ai pas trouvé mieux que de générer deux fichiers, temporaires, mais c'est ce que veut sort.
    Enfin, je verrai...

    Merci à tous pour ces réponses rapides, je vous tiens au courant.

  9. #9
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 323
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 323
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    mon doigt a glissé où ?
    tu te demandes vraiement ? il a glissé hors d'une touche - sur aucune en fait
    Ou bien (plus probablement), tu repassais de la main droite, répondais de la main gauche et regardais la télé
    le second parametre du echo echo "${listenow[i]}" "$listeprv[i]}"https://www.developpez.net/forums/d1...e/#post9513434

  10. #10
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    18 264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 18 264
    Par défaut
    J'y avais pensé mais je me suis dit que des messages système pouvaient s'insérer au milieu
    L'idée est dans ce cas de cibler avec grep par exemple.

    Tu peux aussi regarder les dossier /dev/by....
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  11. #11
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 132
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Bonjour,

    Citation Envoyé par chrtophe Voir le message
    L'idée est dans ce cas de cibler avec grep par exemple.
    pour utiliser grep il me faudrait connaitre la string à chercher, c'est l'histoire de l'œuf et de la poule,

    Citation Envoyé par chrtophe Voir le message
    Tu peux aussi regarder les dossier /dev/by....
    C'est un peu la même chose que /proc/partitions.


    @N_Bah :
    je n'arrive pas à faire fonctionner tes lignes en mode autonome, dans une boucle genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    tantque listeavant = listemaintenant
      update listemaintenant
      sleep 1 sec
    sinon
      stoppe boucle
      analyse différence( listeavant, listemaintenant)
      affiche résultat
    fin
    Pour info, avec comm, je fais ainsi :
    Code bash : 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
    #!/bin/bash
     
    cat /proc/partitions | grep sd > /tmp/listprv.lst 
    cat /proc/partitions | grep sd > /tmp/listnow.lst 
     
    # contrôles
    #echo "listprv.lst"
    #cat /tmp/listprv.lst
    #echo "listnow.lst"
    #cat /tmp/listnow.lst
     
    run="1"
    while [ $run == "1" ] 
    do 
      date #*pour visu en test
      cat /proc/partitions | grep sd > /tmp/listnow.lst 
      sync
      compar=$(comm -3 <(sort /tmp/listnow.lst) <(sort /tmp/listprv.lst) | awk '{print $4}')
      [ -n "$compar" ] && run="0" && echo "$compar"
      sleep 1
    done

    et ça donne ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    ven. 15 avril 2022 10:38:59 CEST
    ven. 15 avril 2022 10:39:00 CEST
       *** insertion clé ***
    ven. 15 avril 2022 10:39:01 CEST
    sdd
    sdd1
    et le script s'arrête, et c'est exactement ce que je veux, le seul souci (qui n'en est pas vraiment un), c'est l'obligation d'utiliser des fichiers quand des variables auraient suffi, mais ça se mélange les pinceaux...

    @flodelarab :
    merci pour ta ligne avec comm
    Mais je n'ai rien compris à ta proposition avec awk, désolé.

    Bonne journée, je vais être moyennement libre, aujourd'hui.

Discussions similaires

  1. Réponses: 8
    Dernier message: 30/01/2017, 16h38
  2. correspondance deux tableaux avec des boucles
    Par ndiayediop2 dans le forum R
    Réponses: 9
    Dernier message: 21/08/2015, 14h48
  3. [XL-2007] comparer deux tableaux avec VBA
    Par anstech dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 15/01/2014, 14h36
  4. Réponses: 4
    Dernier message: 19/07/2012, 10h41
  5. Réponses: 8
    Dernier message: 02/12/2010, 19h39

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