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

Python Discussion :

Doublons de lignes dans fichier: travail complexe!


Sujet :

Python

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    3
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2010
    Messages : 3
    Par défaut Doublons de lignes dans fichier: travail complexe!
    Bonjour,

    A mon taf, on utilise un systeme centralisé de gestion des users/groups, dans des fichiers à plat sur un serveur central.
    Les fichiers concernés sont déployés via des mecanismes de rsync sur les serveurs cibles, et les utilisateurs/groupes créés en fonction des déclarations

    Le séparateur de champ dans les 2 fichiers est un ":".
    Le fichier des utilisateurs ressemble à:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ALLaix:a770343:qFSH9.4k1NUmw:1000343:ass:operator,admsyst:/home/a770343:BOUCHER Jason:true:true:true:false:ALL::0:5:0:false:0:0:0:0:2:3:8:8:0:0:2097151:-1:262144:65536:2097151:65536:::::::22:2000:::
    Explication de la ligne:
    ALLaix: serveurs cibles à déployer.
    Peut prendre comme valeur ALL, ALLaix, ALLlinux, ou aussi <hostname> pour un serveur précis.
    a770343: login
    qFSH9.4k1NUmw: hash du mot de passe du compte
    1000343: UID du compte
    ass: groupe primaire
    operator,admsyst: groupes secondaires
    /home/a770343: homedir
    BOUCHER Jason: finger info (c'est moi! )

    Le reste des champs n'ont pas d'importance dans ce que je veux faire.

    Le fichier des groupes ressemble à:
    Explication de la ligne:
    ALL: serveurs cibles à déployer.
    Peut prendre comme valeur ALL, ALLaix, ALLlinux, ou aussi <hostname> pour un serveur précis.
    soutien: groupe
    !: pas d'importance pour notre reflexion
    1001: GID
    A: pas d'importance pour notre reflexion


    Information importante

    1°) Lors de la création des utilisateurs/groupes sur un serveur particulier, le fichier qui va bien est lu séquentiellement, cad qu'une ligne n+1 écrasera ce qu'une ligne n peut apporter. L'ordre des lignes dans le fichier a une forte importance.
    On veut donc, qu'il y ait d'abord les "ALL", puis les "ALLlinux" ou "ALLaix", et enfin les lignes spécifiques à un serveur.

    Maintenant, voici ce que je veux faire:

    Je me suis apercu donc que dans mes fichiers (utilisateurs ou groupes, peu importe), il pouvait exister une ligne ALL en début de fichier, et plus loin dans le fichier, une ligne serveur_specifique, precisant les memes informations.

    Je voudrais donc "nettoyer" ces fichiers.

    Si besoin de plus d'infos, ou de fichiers de travail, n'hésitez pas à me contacter!

    Merci mille fois de vos idées/réflexions!!


    Jason

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Bonjour,


    Bienvenue sur le forum.



    C’est bien expliqué, c’est agréable.
    Quoiqu’il reste des points pas clairs pour moi.

    ALLaix: serveurs cibles à déployer.
    Peut prendre comme valeur ALL, ALLaix, ALLlinux, ou aussi <hostname> pour un serveur précis.
    Veux tu dire qu’à la place de ALLaix, il peut y avoir les chaînes ALL, ALLaix, ALLlinux, ou <hostname> ?

    <hostname> étant d’ailleurs, je suppose un nom générique pour signifier que ça peut être n’importe quoi : <jarnac>, <Washington>, <Lulu>, <Alpha Centauri A >, etc...?



    Je voudrais donc "nettoyer" ces fichiers.
    OK. Mais que signifie ’nettoyer’ ?
    Je suppose qu’il faut comprendre que tu veux éliminer une des deux lignes ? En fonction de quel critère ? Toujours la première ? Toujours la seconde ? Y a-t-il incidence sur l’ordre ?



    Quelle est ta difficulté finalement ?



    Où est le 1°) ?

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    3
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2010
    Messages : 3
    Par défaut Merci de l'aide!
    Bonjour eyquem,

    Tout d'abord merci de l'accueil!

    Ensuite, pour répondre à tes questions:



    Veux tu dire qu’à la place de ALLaix, il peut y avoir les chaînes ALL, ALLaix, ALLlinux, ou <hostname> ?
    Effectivement, le premier champ prend comme valeurs ALL, ALLlinux, ALLaix, ou un nom générique de serveur.

    OK. Mais que signifie ’nettoyer’ ?
    Nettoyer veut effectivement dire enlever une ligne "superflue" dans le fichier. L'ordre des lignes dans le fichier a une forte incidence, puisque le fichier est parsé sequentiellement. Je m'explique.
    Prenons une ligne commencant par "ALLlinux", définissant les variables de création d'un utilisateur, donc avec son UID, groupe primaire, secondaires...
    exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ALL:a770343:qFSH9.4k1NUmw:1000343:ass:operator,admsyst:/home a770343:BOUCHER Jason:true:true:true:false:ALL::0:5:0:false:0:0:0:0:2:3:8:8:0:0:2097151:-1:262144:65536:2097151:65536:::::::22:2000:::
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    slzk2k:a770343:qFSH9.4k1NUmw:1000343:operator,admsyst,soutien:/home/a770343:BOUCHER Jason:true:true:true:false:ALL::0:5:0:false:0:0:0:0:2:3:8:8:0:0:2097151:-1:262144:65536:2097151:65536:::::::22:2000::
    On voit bien que la 1iere ligne va créer mon compte sur toutes les machines, dont la slzk2k. Puis la 2ieme ligne commencant par "slzk2k" sera "executée". On voit bien qu'a part le premier champ, "ALL" ou "slzk2k", la meme operation sera effectuée, mais en ajoutant un groupe secondaire "soutien" à mon compte sur cette machine "slzk2k".
    Le but du jeu est donc de pouvoir virer les lignes identiques hormi strictement le premier champ.

    exemple:
    Si dans le fichier des utilisateurs on a:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ALL:a770343:qFSH9.4k1NUmw:1000343:ass:operator,admsyst:/home a770343:BOUCHER Jason:true:true:true:false:ALL::0:5:0:false:0:0:0:0:2:3:8:8:0:0:2097151:-1:262144:65536:2097151:65536:::::::22:2000:::
    slzk2k:a770343:qFSH9.4k1NUmw:1000343:operator,admsyst,soutien:/home/a770343:BOUCHER Jason:true:true:true:false:ALL::0:5:0:false:0:0:0:0:2:3:8:8:0:0:2097151:-1:262144:65536:2097151:65536:::::::22:2000::
    slz92a:a770343:qFSH9.4k1NUmw:1000343:operator,admsyst:/home/a770343:BOUCHER Jason:true:true:true:false:ALL::0:5:0:false:0:0:0:0:2:3:8:8:0:0:2097151:-1:262144:65536:2097151:65536:::::::22:2000::
    A la fin, apres nettoyage, on ne doit avoir que la 1iere et la 2ieme.
    Si tu le souhaites, on peut en parler via mail ou autre?

    Merci de ton coup de main.

  4. #4
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Pour ALL c'est faisable, mais pour ALLlinux et ALLaix, comment savoir si une machine donnée tourne en AIX ou en Linux ?

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    J'ai écrit un code en fixant moi même ce qui est voulu, par manque d'information suffisante sur ce que tu veux faire.


    En effet, quand tu dis

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ALL:a770343:qFSH9.4k1NUmw:1000343:ass:operator,admsyst:/home a770343:BOUCHER Jason:true:true:true:false:ALL::0:5:0:false:0:0:0:0:2:3:8:8:0:0:2097151:-1:262144:65536:2097151:65536:::::::22:2000:::
    slzk2k:a770343:qFSH9.4k1NUmw:1000343:operator,admsyst,soutien:/home/a770343:BOUCHER Jason:true:true:true:false:ALL::0:5:0:false:0:0:0:0:2:3:8:8:0:0:2097151:-1:262144:65536:2097151:65536:::::::22:2000::
    slz92a:a770343:qFSH9.4k1NUmw:1000343:operator,admsyst:/home/a770343:BOUCHER Jason:true:true:true:false:ALL::0:5:0:false:0:0:0:0:2:3:8:8:0:0:2097151:-1:262144:65536:2097151:65536:::::::22:2000::
    A la fin, apres nettoyage, on ne doit avoir que la 1iere et la 2ieme.
    .....la 3ième ligne doit elle être éliminée parce qu'elle vient après la 2ième ligne qui lui est semblable
    ou bien parce qu'elle ne comporte pas "soutien" ?


    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
    dic = {}
    coll_serveurs = ('tombouctou','toulouse','caen','brest')+ ('ALL','ALLaix','ALLlinux')
    dicall = dict(zip(coll_serveurs,[ [] for i in xrange(len(coll_serveurs)) ] ))
    exclure = set([])
     
    with open('boucher.txt','rb') as f:
     
        for cnt,ln in enumerate(f):
     
            try:
                serveur,login,cocaine,uid,grp,suite = ln.split(':',5)
     
                if serveur in coll_serveurs:
                    if uid in dicall[serveur]:
                        exclure.add(cnt)
                    else:
                        dicall[serveur].append(uid)
     
                elif uid in dic:
                    if 'soutien' in grp:
                        if 'soutien' not in dic[uid]:
                            exclure.add(dic[uid][0])
                            dic[uid].append('soutien')
                        else:
                            exclure.add(cnt)
                    else:
                        exclure.add(cnt)
     
                else: # cad uid not in dic
                    if 'soutien' in grp:
                        dic[uid] = ['soutien']
                    else:
                        dic[uid] = [cnt,'sans soutien']
     
            except:
                pass
     
        f.seek(0)
        g = open('boucher.txt','r+b')
        [ g.write(ln) for i,ln in enumerate(f) if i not in exclure ]
        g.truncate()
        g.close()

    Le principe du programme est de parcourir une première fois l'ensemble du fichier pour repérer les lignes qui sont à éliminer.
    Les lignes à garder sont celles qui apparaissent la première fois avec :
    - soit un couple (serveur,uid) dans lequel serveur appartient au tuple coll_serveurs,
    - soit les lignes dont le serveur n'appartient pas à ce tuple, mais une seule ligne peut être gardée en sus des lignes de mêmes uid que ci-dessus. Compte tenu aussi qu'une ligne avec le mot "soutien" est prioritaire sur une ligne sans ce mot, même si elle est après cette dernière dans la succession du fichier.


    La difficulté est de trouver une manière de classer les lignes correspondant à un seul UID sans consommer de la mémoire comme cela aurait lieu en stockant toutes les lignes avant leur classement.


    Puis de parcourir une deuxième fois en recopiant le fichier sur lui-même en excluant du recopiage les lignes qui ont été repérées par l'objet 'exclure'



    Ce code est une solution avec les contraintes que je me suis données. Il faudra modifier en fonction de ce que tu veux eactement


    Tu peux jeter un œil sur le post suivant pour l'aspect recopiage de fichier avec élimination de lignes
    http://www.developpez.net/forums/d88...n/#post5033718

  6. #6
    Membre chevronné
    Homme Profil pro
    Responsable du parc et des réseaux de télécommunication
    Inscrit en
    Mai 2003
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Responsable du parc et des réseaux de télécommunication
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2003
    Messages : 290
    Par défaut
    Bonjour,
    Une autre possibilité, à améliorer ...
    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
    #!/usr/bin/env python
     
    file=open("f.txt","r").readlines()
    f=[l.split(":",1) for l in file]
    result=[]
     
    #decorateur. Lance directement la coroutine
    def coroutine(func):
        def start(*args,**kwargs):
            cr = func(*args,**kwargs)
            cr.next()
            return cr
        return start
     
    @coroutine
    def nettoie(value):
        while True:
            line=(yield)
            if value == line[1] :
                f.remove(line)
     
    for i in [line for line in f if line[0]=="ALL"]:
        result.append(i)    #result contient les lignes commencant par "ALL"
        f.remove(i)
     
    for i in result:
        fonc=nettoie(i[1])
        for line in f[:] :
            fonc.send(line)
    result.extend(f)    #On ajoute la liste nettoyee
    result="".join([":".join(line) for line in result])
    print result

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    3
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Mars 2010
    Messages : 3
    Par défaut Re!
    Bonjour à tous,

    Merci de votre contribution. Je vous dirai dès demain si l'une des solutions me convient, j'etais en congés.

    Alors, quelques explications:
    Si une ligne n est égale à une ligne n, hors le premier champ "ALL,ALLaix,ALLlinux", on la dégage, en effet, si un compte doit etre créé sur une machine x, alors qu'il y a deja une ligne "globale" (ALL, ALLaix, ALLlinux), ca ne sert a rien qu'elle y soit!

    Sinon, pour répondre quant à comment déterminer ALLaix, ou ALLlinux, il y a une procédure dans le magnifique script perl qui le détermine. Moi, je ne cherche pas à modifier le big script, mais juste à nettoyer le fichier des utilisateurs et des groupes!

Discussions similaires

  1. [Librairies] Inserer lignes dans fichier RTF
    Par tit_oune dans le forum Bibliothèques et frameworks
    Réponses: 5
    Dernier message: 04/05/2012, 11h21
  2. ecrire a la ligne dans fichier texte.
    Par zulot dans le forum Langage
    Réponses: 7
    Dernier message: 12/09/2006, 13h02
  3. Réponses: 3
    Dernier message: 16/08/2006, 18h32
  4. prb retour a la ligne dans fichier txt telecharge avec php
    Par supersonicblonde dans le forum Langage
    Réponses: 3
    Dernier message: 08/06/2006, 15h20
  5. [Unix KSH] Ajout caractère fin de ligne dans fichier
    Par -COil- dans le forum Autres langages
    Réponses: 1
    Dernier message: 04/05/2006, 17h06

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