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 :

[Exercice] Fichiers passwd


Sujet :

Shell et commandes GNU

  1. #1
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut [Exercice] Fichiers passwd
    Bin quand même, un petit avant de partir une semaine:

    Je veux créer un fichier /etc/passwd à partir de deux autres: Il y a passwd.principal et passwd.secondaire.
    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
    Fichier passwd.principal:
    =========================
    moi:mon-passe-mot:100:100:Moi, c'est moi:/maison/moi:/bin/bash
    toi:ton-passe-mot:101:100:Toi, c'est toi:/appart/toi:/bin/bash
    lui:son-passe-mot:102:100:Lui, c'est lui:/carton/lui:/bin/babash
    eux:leurs-passe-mots:103:100:Eux, c'est pas moi:/lazone/eux:/bin/isariv
    michu:secret:104:100:Mme Michu:/chez/germaine:/bin/quoi
    toit:chaume:105:100:Chapeau maison:/dumonde/toit:/bin/sahalor
     
    Fichier passwd.secondaire:
    ==========================
    elle:son-passe-mot:200:100:Elle, mignonne:/paschezmoi/dommage/elle:/bin/bash
    nous:nos-passe-mots:201:100:On est les meilleurs:/hlm/bleme/nous:/bin/bash
    moi:mon-autre-passe-mot:202:100:Fous la m...:/chateau/espagne:/bin/bash
    vous:vos-passe-mots:203:100:Vous, petes de thunes:/16e/beaux/quartiers:/bin/bash
    S'il y a des noms en double entre les deux fichiers, ce sont ceux de passwd.principal qui ont la priorité: il faut alors supprimer ceux de passwd.secondaire. Et le résultat devra être trié.

    Un bon p'tit script Bash pour nous emballer tout ça, Mame Michu?

  2. #2
    Rédacteur/Modérateur
    Avatar de Winnt
    Homme Profil pro
    budget et contrôle de gestion
    Inscrit en
    Décembre 2006
    Messages
    1 978
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France

    Informations professionnelles :
    Activité : budget et contrôle de gestion
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 978
    Par défaut
    Salut,

    Voila ma contribution
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #!/bin/bash
    # copie du fichier pour ne pas le modifier
    cat passwd.secondaire > passwd.final
    for var in $(cut -d: -f1 passwd.principal)
    do
    	grep -q "^$var" passwd.secondaire && sed -i -e "s%$(grep "^$var" passwd.secondaire)%%" -e "/^$/d" passwd.final
    done
    sort --output=passwd.final passwd.principal passwd.final
    Winnt
    Merci de lire les règles du forum LaTeX et Qu'est ce qu'un ECM ?.
    N'hésitez pas à parcourir la FAQ la réponse y est peut-être déjà.
    Pensez au bouton si votre problème est résolu.


    C'est en Linuxant qu'on devient .... geek
    Et c'est en LateXant qu'on devient flemmard
    Mon blog tout neuf.
    Articles : présentation de la distribution Gentoo, Les index sous LaTeX et leur personnalisation.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 737
    Par défaut
    pas mieux

    nouvelles versions des fichiers passwd principal et secondaire prise en compte
    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
    #!/bin/bash
    
    pass="test/passwd"
    >"${pass}.wrk"
    
    # lire chaque ligne de la concaténation des deux fichiers passwd (principal et secondaire)
    while read line
       do
    # si aucune ligne du fichier temporaire ne commence par le nom d'utilisateur...
          if [ -z "$(egrep "^${line%%:*}" ${pass}.wrk)" ]
             then
                echo "$line" >> "${pass}.wrk"       # ...inscription de la ligne dans le fichier temporaire
          fi
    done < <(cat "${pass}.principal" "${pass}.secondaire")
    
    # trier le fichier temporaire et rediriger le résultat vers passwd
      sort -d -t':' -k1,1 "${pass}.wrk" >"$pass"
    
    # supprimer le fichier temporaire
      rm "${pass}.wrk"
    
    # afficher le fichier passwd
      cat "$pass"
    elle:son-passe-mot:200:100:Elle, mignonne:/paschezmoi/dommage/elle:/bin/bash
    eux:leurs-passe-mots:103:100:Eux, c'est pas moi:/lazone/eux:/bin/isariv
    lui:son-passe-mot:102:100:Lui, c'est lui:/carton/lui:/bin/babash
    michu:secret:104:100:Mme Michu:/chez/germaine:/bin/quoi
    moi:mon-passe-mot:100:100:Moi, c'est moi:/maison/moi:/bin/bash
    nous:nos-passe-mots:201:100:On est les meilleurs:/hlm/bleme/nous:/bin/bash
    toi:ton-passe-mot:101:100:Toi, c'est toi:/appart/toi:/bin/bash
    toit:chaume:105:100:Chapeau maison:/dumonde/toit:/bin/sahalor
    vous:vos-passe-mots:203:100:Vous, petes de thunes:/16e/beaux/quartiers:/bin/bash

  4. #4
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Voici ma solution:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/bin/bash
     
    sort -t ':' -k 1,1 passwd.principal | tee passwd.1 | cut -d ':' -f 1 > passwd.2
    sort -t ':' -k 1,1 passwd.secondaire | tee passwd.3 | cut -d ':' -f 1 > passwd.4
    join -t ':' passwd.1 passwd.4 > passwd.5
    join -t ':' -v 1 passwd.1 passwd.4 >> passwd.5
    join -t ':' -v 1 passwd.3 passwd.2 >> passwd.5
    sort -t ':' -k 1,1 passwd.5 > passwd.final
    rm -f passwd.[1-5]
    Edit: Optimisation... grâce au code de winnt qui m'a fait prendre conscience que sort peut trier plusieurs fichiers en une seule fois.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #!/bin/bash
     
    sort -t ':' -k 1,1 passwd.principal | tee passwd.1 | cut -d ':' -f 1 > passwd.2
    sort -t ':' -k 1,1 passwd.secondaire > passwd.3
    join -t ':' -v 1 passwd.3 passwd.2 > passwd.4
    sort -t ':' -k 1,1 passwd.1 passwd.4 > passwd.final
    rm -f passwd.[1-4]
    Re-edit: re-optimisation... join peut lire la sortie standard pour une des entréee. Et donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #!/bin/bash
     
    sort -t ':' -k 1,1 passwd.principal | tee passwd.1 | cut -d ':' -f 1 > passwd.2
    sort -t ':' -k 1,1 passwd.secondaire | join -t ':' -v 1 - passwd.2 > passwd.3
    sort -t ':' -k 1,1 passwd.1 passwd.3 > passwd.final
    rm -f passwd.[1-3]

  5. #5
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Afin de bien être sûr que les scripts fonctionnent correctement, pourriez-vous reprendre les deux fichiers initiaux (j'ai fait une petite erreur hier soir). Je vous mets aussi le fichier qu'il faut obtenir.

    Fichier passwd.principal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    moi:mon-passe-mot:100:100:Moi, c'est moi:/maison/moi:/bin/bash
    toi:ton-passe-mot:101:100:Toi, c'est toi:/appart/toi:/bin/bash
    lui:son-passe-mot:102:100:Lui, c'est lui:/carton/lui:/bin/babash
    eux:leurs-passe-mots:103:100:Eux, c'est pas moi:/lazone/eux:/bin/isariv
    michu:secret:104:100:Mme Michu:/chez/germaine:/bin/quoi
    Fichier passwd.secondaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    elle:son-passe-mot:200:100:Elle, mignonne:/paschezmoi/dommage/elle:/bin/bash
    nous:nos-passe-mots:201:100:On est les meilleurs:/hlm/bleme/nous:/bin/bash
    moi:mon-autre-passe-mot:202:100:Fous la m...:/chateau/espagne:/bin/bash
    vous:vos-passe-mots:203:100:Vous, petes de thunes:/16e/beaux/quartiers:/bin/bash
    toit:chaume:105:100:Chapeau maison:/dumonde/toit:/bin/sahalor
    Fichier passwd.final:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    elle:son-passe-mot:200:100:Elle, mignonne:/paschezmoi/dommage/elle:/bin/bash
    eux:leurs-passe-mots:103:100:Eux, c'est pas moi:/lazone/eux:/bin/isariv
    lui:son-passe-mot:102:100:Lui, c'est lui:/carton/lui:/bin/babash
    michu:secret:104:100:Mme Michu:/chez/germaine:/bin/quoi
    moi:mon-passe-mot:100:100:Moi, c'est moi:/maison/moi:/bin/bash
    nous:nos-passe-mots:201:100:On est les meilleurs:/hlm/bleme/nous:/bin/bash
    toi:ton-passe-mot:101:100:Toi, c'est toi:/appart/toi:/bin/bash
    toit:chaume:105:100:Chapeau maison:/dumonde/toit:/bin/sahalor
    vous:vos-passe-mots:203:100:Vous, petes de thunes:/16e/beaux/quartiers:/bin/bash

  6. #6
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    awk -F: '{
        if (!($1 in h))
            h[$1] = $0
    }
     
    END {
        n = asorti(h, s)
        for (i=1; i<=n; i++)
            print h[s[i]]
    }' passwd.principal passwd.secondaire

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 737
    Par défaut
    version 2, qui devrait tenir compte de ce que les fichiers passwd.principal et passwd.secondaire peuvent ne pas se terminer par un retour à la ligne (ce qui arrive lorsqu'on les remplit avec printf)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/bin/bash
     
    >passwd.tmp
    while read line; do
       egrep -q "^${line%%:*}" passwd.tmp || echo "$line" >> passwd.tmp
    done < <(echo -e "$(<passwd.principal)\\n$(<passwd.secondaire)")
     sort -d -t':' -k1,1 passwd.tmp >passwd.final
     rm passwd.tmp
    # cat passwd.final
    edit: j'avais cru pouvoir utiliser un tableau, mais je viens de me rendre que
    1- il n'était pas correctement rempli
    2- c'est inutile!
    Ce qui fait que je me retrouve avec ce que m'a soufflé jmelyn.
    .../...
    Bon, finalement, à force... avec un tableau:
    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
    #!/bin/bash
     
    >test/passwd.tmp
     
    oifs="$IFS"
    IFS="
    "
    tabl=( $(echo -e "$(<test/passwd.principal)\\n$(<test/passwd.secondaire)") )
    IFS="$oifs"
     
    for enrg in "${tabl[@]}"
       do egrep -q "${enrg%%:*}" test/passwd.tmp || echo "$enrg" >> test/passwd.tmp
    done
    sort -d -t':' -k1,1 test/passwd.tmp > test/passwd.final
    rm test/passwd.tmp
     
    cat test/passwd.final
    Non, mais alors... ;-)

  8. #8
    Rédacteur/Modérateur
    Avatar de Winnt
    Homme Profil pro
    budget et contrôle de gestion
    Inscrit en
    Décembre 2006
    Messages
    1 978
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France

    Informations professionnelles :
    Activité : budget et contrôle de gestion
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 978
    Par défaut
    Salut,

    Voilà mon script modifié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/bin/bash
    # copie du fichier pour ne pas le modifier
    cat passwd.secondaire > passwd.final
    for var in $(cut -d: -f1 passwd.principal)
    do
    	grep -q "^$var:" passwd.secondaire && sed -i -e "s%$(grep "^$var:" passwd.secondaire)%%" -e "/^$/d" passwd.final
    done
    sort --output=passwd.final passwd.principal passwd.final
    une toute petite modification (en rouge) et ca marche
    Winnt
    Merci de lire les règles du forum LaTeX et Qu'est ce qu'un ECM ?.
    N'hésitez pas à parcourir la FAQ la réponse y est peut-être déjà.
    Pensez au bouton si votre problème est résolu.


    C'est en Linuxant qu'on devient .... geek
    Et c'est en LateXant qu'on devient flemmard
    Mon blog tout neuf.
    Articles : présentation de la distribution Gentoo, Les index sous LaTeX et leur personnalisation.

  9. #9
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Je vais tenter d'analyser les scripts qui ont été postés. Cela aidera à voir les points forts de chaque solutions. Les commentaires sont les bienvenus, bien sûr: dites-moi si je me trompe. Bonne lecture!

    winnt

    Méthode:
    1) Prendre le fichier secondaire, retirer les doublons et sauver dans un fichier temporaire.
    2) Assembler le fichier principal et le fichier temporaire, trier et sauver.

    Points forts:
    * La construction utilisant '&&' est claire et élégante: elle utilise la fonctionnalité de if en étant plus compacte (pour des commandes simples). Ici, si le retour de la commande grep est 0 (true) lorsqu'une ligne est trouvée dans le fichier, alors la suite est exécutée, c'est-à-dire le sed pour la suppression de la ligne qui fait doublon.
    * sed -i fait les modifications directement dans le fichier, pas besoin de faire la sortie dans un nouveau fichier puis de renommer. En fait, c'est sed qui fait tout ça tout seul.
    * sort fichier_1 fichier_2 > fichier_3 assemble les deux fichiers, les trie et les sauve... en une seule commande!

    Attention:
    * Au tout début, le cat (passage par stdout) n'est pas nécessaire pour la copie de fichier: cp est plus direct.
    * grep -q n'est pas portable, il vaut mieux le standard grep ... > /dev/null. Bon, on s'en fout.
    * Le pattern du grep n'est pas correct: "^$var" est insuffisant car 'toit' sera supprimé parce qu'il commence comme 'toi', un autre user. Le pattern correct est "^$var:", ':' terminant le champ user. Bon, t'as corrigé...
    * La suppression par sed peut être faite par la commande d (delete) plutôt que s (subsitute): sed -i -e '/'$var'/d' passwd.final
    * Le sort final est dangereux: un fichier sert d'entrée et de sortie. Il faudrait gérer le buffer (-S) mais cela devient moins lisible, moins compréhensible. Il vaut mieux passer par un fichier intermédiaire différent: passwd.tmp, et le résultat final dans passwd.final.
    * Sans plus d'option, sort trie sur toute la ligne. On obtient le user 'toit' avant 'toi'. Il faut dire à sort de trier sur le premier champ uniquement: sort -t ':' -k 1,1.

    Efficacité:
    Sur ma machine, j'obtiens environ 18ms.

    N_BaH
    Méthode:
    1) Assembler les deux fichiers (principal puis secondaire).
    2) Pour chaque ligne obtenue, si elle n'existe pas encore, on l'ajoute au nouveau fichier.

    Points forts:
    * Chargement des deux fichiers en mémoire. Ce peut aussi être un handicap si les fichiers font des GiB, mais pas de souci avec les fichiers passwd.
    * Même construction élégante avec '||' cette fois: (e)grep trouve le pattern (doublon) ou alors il ajoute la ligne.
    * Utilisation avancée des redirections: '> fichier' est plus concis que 'rm fichier; touch fichier'. De même '$(< fichier)' vaut un '$(cat fichier)' mais en plus rapide.
    * Utilisation de pattern de variable: '${line%%:*}' prend la variable $line et lui supprime autant de ':<champ>' que possible; résultat, il ne reste que le premier champ: le user.

    Attention:
    * Pour l'assignation d'IFS, il est possible de mettre le retour à la ligne sans vraiment passer à la ligne: IFS=$'\n'.
    * On peut faire l'assignation d'IFS dans la liste de commande de tabl: tabl=$(IFS=$'\n'; ...), il n'est alors pas besoin de revenir en arrière.
    * Le pattern du grep n'est pas correct: il manque ':' pour fermer le champ parce que '^toi' est inclus dans '^toit', alors que '^toi:' ne l'est pas dans '^toit:'.
    * grep -q n'est pas standard... oui on s'en fout.
    * echo -e accepte les caractères échappés comme '\n'. Inutile de doubler le '\', echo -e '\n' fonctionne.

    Efficacité:
    Environ 10 ms (la version précédente était à 21ms, le chargement en mémoire fut un bon choix!).

    jmelyn
    Méthode:
    En fait, la même que winnt, mais avec la commande join qui provient des bases de données.

    Points forts:
    * Pas de boucle en langage de script, donc plus rapide. Bonne utilisation de join.

    Attention:
    * Que de fichiers temporaires! L'efficacité acquise par le join est perdue par les manipulations multiples!
    * Il reste une erreur: il n'y a pas de suppression de lignes vides: sed -e '/^$/d' juste avant d'enregistrer le fichier final.

    Efficacité:
    Environ 10ms.

    Matafan
    méthode:
    Programme awk, utilisant les tableaux associatifs pour dédoublonner. Il faudra attendre Bash version 4 pour les avoir en natif dans le shell. Le principe est simple: une première assignation est effectuée: tableau["moi"] = "moi:mon-pass-mot:100:100:...". Lorsque la seconde arrive (doublon), la case tableau["moi"] existe déjà et n'est pas sur-écrite grâce au if. Les deux fichiers sont lus et chargés en mémoire, dans le tableau. Puis ce dernier est trié selon les indices (asorti) et affichés.

    Points forts:
    * Lisibilité et simplicité du programme awk.
    * Utilisation des tableaux associatifs (simplicité).
    * Chargement et travail en mémoire: les fichiers password ne sont pas si gros. Attention toutefois s'il s'agit de fichiers monstrueux.
    * Pas de fichier temporaire.

    Attention:
    * Il est autorisé d'avoir des variables de plus d'un caractère: h, s, i, n: ne sont pas très lisibles.
    * Il manque l'enregistrement dans le fichier final '> passwd.final'. Faut bien trouver quelque chose à redire, hein?

    Efficacité:
    Attention, Matafan explose les compteurs: 4ms.

  10. #10
    Rédacteur/Modérateur
    Avatar de Winnt
    Homme Profil pro
    budget et contrôle de gestion
    Inscrit en
    Décembre 2006
    Messages
    1 978
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France

    Informations professionnelles :
    Activité : budget et contrôle de gestion
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 978
    Par défaut
    Salut,

    Citation Envoyé par jmelyn
    * La suppression par sed peut être faite par la commande d (delete) plutôt que s (subsitute): sed -i -e '/'$var'/d' passwd.final
    Exact mais pas dans ce cas.
    Raison pour laquelle je modifie / par % dans la première commande sed.
    Avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    moi:mon-passe-mot:100:100:Moi, c'est moi:/maison/moi:/bin/bash
    sort une erreur. Le slash qui n'est pas échappé.
    Donc on nettoie la ligne puis on la supprime.

    * Au tout début, le cat (passage par stdout) n'est pas nécessaire pour la copie de fichier: cp est plus direct.
    * grep -q n'est pas portable, il vaut mieux le standard grep ... > /dev/null. Bon, on s'en fout.
    Grmmmbllll => Winnt

    Mais pas si mal pour un débutant
    Winnt
    Merci de lire les règles du forum LaTeX et Qu'est ce qu'un ECM ?.
    N'hésitez pas à parcourir la FAQ la réponse y est peut-être déjà.
    Pensez au bouton si votre problème est résolu.


    C'est en Linuxant qu'on devient .... geek
    Et c'est en LateXant qu'on devient flemmard
    Mon blog tout neuf.
    Articles : présentation de la distribution Gentoo, Les index sous LaTeX et leur personnalisation.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 737
    Par défaut
    Citation Envoyé par jmelyn
    On peut faire l'assignation d'IFS dans la liste de commande de tabl: tabl=$(IFS=$'\n'; ...)
    Mais, alors ce n'est plus un tableau : c'est une variable sur plusieurs lignes!
    Ce qui pourrait ne pas être catastrophique, puisqu'on ne se sert pas des indices pour se référer à tel ou tel enregistrement...si le script fonctionnait encore ^^
    L'ensemble est correctement trié. Cependant, cela affiche les deux "moi"...?

    À moins d'en revenir à un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while read line; do...done <<<"$tabl"
    .../...
    Tiens? J'ai essayé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    echo -e "$(<passwd.principal)\n$(<passwd.secondaire)" |\
     sort -d -t':' -k1,1 -u
    et la sortie a l'air correct, mais ce n'est peut-être pas très fiable
    ...
    ?

  12. #12
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    792
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 792
    Par défaut
    Pour les fanatiques des one-liners:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     awk -F: '! _flag[$1] {_flag[$1]=1; print}' principal secondaire | sort > final
    Il n'est pas dit que le pipe vers sort soit plus lent que l'utilisation des natives asort et asorti de awk. A tester.

    Note: les fonctions asort et asorti ne se trouvent pas dans awk POSIX. Elles sont apparues dans GNU awk (gawk 3.1). Pas que ce soit important, sauf peut-être pour la portabilité vers Unix. Toutes les distro Linux utilisent gawk, à ma connaissance)

  13. #13
    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
    Ah oui j'ai été un peu bête de faire un if dans le premier bloc. Il vaut mieux utiliser la condition du bloc comme tu l'as fais.

  14. #14
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    792
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 792
    Par défaut
    Awk étant connu (et apprécié) pour sa concision, on peut même faire un poil plus court:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk -F':' '!_[$1] {_[$1]=1}1' primaire secondaire | sort > final
    ou bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     awk -F':' '!_[$1]&&_[$1]=1||1' primaire secondaire | sort > final
    Moins lisible. Limite Obfuscated code Contest

  15. #15
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Bonjour,

    J'ai deux questions pour les dernières solutions de Ripat:

    • Est-ce que le '_' a une signification particulière ou est-ce une variable comme var ou toto?
    • À quoi sert le '1' après les accolades. S'agit-il d'une sorte de else?

    Ça pourrait m'intéresser, j'utilise souvent awk dans mes scripts.

  16. #16
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Une dernière solution, inspirée par winnt et N_BaH, qui me semble la plus simple et en tout cas la plus rapide (2ms):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sort -u -t ':' -k 1,1 passwd.principal passwd.secondaire > passwd.final
    Explications:

    • La commande sort peut prendre plusieurs fichiers en entrée (ici passwd.principal et passwd.secondaire).
    • L'option -u de sort veut dire 'unique', c'est-à-dire que les entrées identiques sont supprimées. Oui, mais lesquelles? La man page indique: output only the first of an equal run. Seule la première des entrées sera conservée, donc l'ordre des fichiers d'entrée est très important: il faut mettre le fichier le plus prioritaire en premier.
    • les options -t ':' -k 1,1 indiquent qu'il faut trier sur le premier champ uniquement et que le séparateur de champ est le caractère ':'.

    Cette solution va m'aider parce qu'elle est générale: en fait, j'ai 5 fichiers en entrée, il me suffira de les mettre par ordre de priorité. C'est cool, merci à tous pour cet exercice finalement pas si évident.

  17. #17
    Rédacteur/Modérateur
    Avatar de Winnt
    Homme Profil pro
    budget et contrôle de gestion
    Inscrit en
    Décembre 2006
    Messages
    1 978
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France

    Informations professionnelles :
    Activité : budget et contrôle de gestion
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 978
    Par défaut
    Voilà une solution simple et élégante je trouve.
    Winnt
    Merci de lire les règles du forum LaTeX et Qu'est ce qu'un ECM ?.
    N'hésitez pas à parcourir la FAQ la réponse y est peut-être déjà.
    Pensez au bouton si votre problème est résolu.


    C'est en Linuxant qu'on devient .... geek
    Et c'est en LateXant qu'on devient flemmard
    Mon blog tout neuf.
    Articles : présentation de la distribution Gentoo, Les index sous LaTeX et leur personnalisation.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 737
    Par défaut
    Pris dans le challenge, j'ai oublié de remercier jmelyn, pour le défi...

    Ce qui peut paraître facile (poser une question, clairement), l'est (ahh! du lait en brochettes ! hmm... !) beaucoup moins, quand, comme jmelyn, on s'engage aussi à apporter une évaluation... !

    Finalement, à ceux qui ont codé le défi en awk (awesome awk!) (et qui sont, par conséquent, disqualifiés d'office ^^) , pour rappel,
    au départ, il s'agissait de coder en bash !
    Merci aussi !

    Merci à tous.

    et merci jmelyn.

  19. #19
    Membre émérite Avatar de jmelyn
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Septembre 2007
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Septembre 2007
    Messages : 703
    Par défaut
    Sympa N_BaH . Je me suis régulièrement rendu compte qu'une solution travaillée à plusieurs est meilleure que celle apportée par une seule personne. C'est la raison de ces exercices (enfin de ce premier). J'apprécie beaucoup les idées originales, les commentaires qui n'ont peut-être rien à voir mais qui initient d'autres solutions. Et awk en fait partie, ne t'en déplaise .

    Comme on le remarque sur le nombre de lecteurs, l'exercice dépasse largement ceux qui y ont contribué. Je trouve important de macher les solutions apportées, d'en sortir les points forts et parfois aussi les points faibles. D'abord ça m'oblige à décortiquer chaque solution et donc à apprendre, mais le partage peut amener de nouvelles idées. Je n'aurais jamais trouvé la dernière solution sans avoir lu et relu les interventions précédentes. Pour moi c'est le point important de l'Open Source. Bon, je passe parfois à côté, ma critique n'est pas correcte, mais je compte sur vous pour me corriger.

    Il n'y a pas de niveau requis, chacun a la possibilité de proposer une solution, de faire une remarque: ça fait avancer le groupe. Et chacun peut proposer un nouvel exercice! Pas trop le temps en ce moment, vu que je tente de conserver 8 heures par jour pour dormir.

  20. #20
    Rédacteur/Modérateur
    Avatar de Winnt
    Homme Profil pro
    budget et contrôle de gestion
    Inscrit en
    Décembre 2006
    Messages
    1 978
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : France

    Informations professionnelles :
    Activité : budget et contrôle de gestion
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 978
    Par défaut
    Salut,

    Complétement d'accord avec jmelyn.
    J'ai pris beaucoup de plaisir à tenter d'apporter une solutions à cet "exercice".
    Et aussi à lire et tenter de comprendre les solutions des autres participants.
    En plus cela permet de voir qu'il n'y a pas une mais plusieurs solutions et que chacune a son intérêt.
    Les critiques si elles sont constructives sont toujours très intéressantes à lire à mon humble avis de débutant
    Winnt
    Merci de lire les règles du forum LaTeX et Qu'est ce qu'un ECM ?.
    N'hésitez pas à parcourir la FAQ la réponse y est peut-être déjà.
    Pensez au bouton si votre problème est résolu.


    C'est en Linuxant qu'on devient .... geek
    Et c'est en LateXant qu'on devient flemmard
    Mon blog tout neuf.
    Articles : présentation de la distribution Gentoo, Les index sous LaTeX et leur personnalisation.

Discussions similaires

  1. Sed et fichier passwd
    Par jmelyn dans le forum Shell et commandes GNU
    Réponses: 2
    Dernier message: 30/10/2009, 10h08
  2. [Turbo Pascal] Exercice fichier séquentiel
    Par agan2012 dans le forum Turbo Pascal
    Réponses: 3
    Dernier message: 07/07/2009, 15h10
  3. fichier PASSWD corrompu
    Par corridea dans le forum Solaris
    Réponses: 1
    Dernier message: 21/03/2008, 00h17
  4. [CVSNT] Pb avec fichier passwd
    Par ego dans le forum CVS
    Réponses: 1
    Dernier message: 28/11/2007, 21h50
  5. Awk - Traiter chaque ligne du fichier passwd
    Par tony montana dans le forum Linux
    Réponses: 7
    Dernier message: 25/03/2004, 10h40

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