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 :

Utilisation du module RE et mise en page d'un extract


Sujet :

Python

  1. #1
    Membre régulier
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Janvier 2012
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2012
    Messages : 97
    Points : 75
    Points
    75
    Par défaut Utilisation du module RE et mise en page d'un extract
    Bonjour,

    Je viens chercher un peu d'aide car je souhaite mieux maitriser le module RE si possible de python (étant débutant) et mettre en forme un fichier selon le résultat

    Premièrement j'ai un fichier contenant des lignes types:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    halt:x:7:0:halt:/sbin:/sbin/halt
    uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
    Je souhaite en extraire le "login", qui ici sera définit comme étant entre le début de ligne et le premier séparateur ":" .
    Ensuite le HOME "/var/spool/login" comprent entre les ":/" et ce, sur les entrées ne contenant que "nologin" en fin de lignes. Pour pimentés le tout je dois formater mon fichier sous forme de colonne bien alignés, les logins ne sont jamais de la même taille idem pour le path du home.

    Le fichier de sortie se présente sous formatage de colonne tel que:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    login1          /home/toto/login1
    login111111     /home/toto/login111111
    C'est la mon point le plus difficile.

    Pour le module RE j'en suis à ciblé entre 2 types de balises faisant office de delimiteur, sur mon exemple, il me sortira le premier login de la premiere ligne "mail" sans tenir compte des lignes finissant par "nologin" ou non.

    Mes codes actuel, après il me faudra l'ajouter dans une boucle AND pour ressortir le path:

    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
    #!/usr/bin/python2.6
    #-*- coding: utf-8 -*-
     
    import re
     
    begin_balise = ''
    end_balise = ':x'
    motif = begin_balise + '.*' + end_balise #construction de la recherche
     
    obj_fichier = open("/home/blanci/Desktop/passwd","r") #fichier a lire
    texte = obj_fichier.read() #lecture fichier
    obj_fichier.close()
    obj_regex = re.search(motif, texte) #recherche avec la construction dans le contenu du fichier
     
     
    if obj_regex is None: # si aucun retour
        print "Pas de resultat reconnaissable dans le fichier."
    else: # sinon j'ecris le login dans le fichier
        texte = obj_regex.group()
        texte = texte.replace(begin_balise, '')
        texte = texte.replace(end_balise, '')
        texte = texte.strip()
        print "Voici le resultat :",texte
        passwd_extract = open('/home/Bureau/passwd_extract.txt', "w")
        passwd_extract.write(texte)
        passwd_extract.close()
    Et pour le moment ma boucle for qui va chercher les lignes en nologin:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #!/usr/bin/python2.6
    #-*- coding: utf-8 -*
     
     
    chaine = "nologin" # Texte à rechercher
     
    print "\n ======== les lignes recherches contiennent: ", chaine, "========\n"
     
    fichier = open("/home/blanci/Desktop/passwd","r") # fichier a lire
    for line in fichier:
        if chaine in line:
            print line.split(" ") #affichage des lignes nologin
    fichier.close()

    Comme préciser au début je débute en python c'est pour ca que pour le moment j'ai 2 codes séparés, pour bien comprendre le fonctionnement de chaque étapes du module et de mes boucles pour les faire fonctionner ensembles par la suite.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Le fichier passwd est compose de lignes contenant un ensemble de "champs" sépares par des ":".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> line = 'mail:x:8:12:mail:/var/spool/mail:/sbin/nologin'
    >>> line.split(':')
    ['mail', 'x', '8', '12', 'mail', '/var/spool/mail', '/sbin/nologin']
    Les champs sont a des indices bien définis.
    On peut écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> HOME=5
    >>> fields = line.split(':')
    >>> fields[HOME]
    '/var/spool/mail'
    >>>
    Je ne comprends pas pourquoi vous vous embêtez avec le module "re" pour des trucs aussi simples.
    Sauf dans le cas ou c'est un devoir a rendre.
    Dans ce cas, c'est a vous de faire l'exercice et de poser des questions plus précises si vous voulez de l'aide.
    note: mes collègues vous répondrons s'ils veulent, moi je préfère profiter du soleil.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Février 2012
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2012
    Messages : 48
    Points : 105
    Points
    105
    Par défaut
    Je n'ai rien compris à l'histoire du home. Mais à priori, nul besoin d'avoir recours au module re dans le cas présenté ici.
    La méthode présenté par wiztrick pour "parser" le csv est la bonne.
    Pour savoir si une ligne se termine par "nologin", il faut utiliser la méthode endswith des strings
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    In [1]: "mail:x:8:12:mail:/var/spool/mail:/sbin/nologin".endswith('nologin')
    Out[1]: True
     
    In [2]: "halt:x:7:0:halt:/sbin:/sbin/halt".endswith('nologin')
    Out[2]: False
    Pour le nombre de colonne fixe, la méthode format des strings est là pour ça.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    In [3]: "{login:15}{home:15}".format(login="login1", home="/home/toto/login1")
    Out[3]: 'login1         /home/toto/login1'
     
    In [4]: "{login:15}{home:15}".format(login="login111111", home="/home/toto/login111111")
    Out[4]: 'login111111    /home/toto/login111111'
    Et si la taille maximum est inconnue, suffit de préparer la string à formater
    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
    In [5]: logins = ['login1', 'login111111', 'login78Y789909709898877777876868768']
     
    In [6]: length = len(max(logins)) + 2  # On rajoute un 2 pour se donner un peu de marge
     
    In [7]: length
    Out[7]: 38
     
    In [8]: template = "{{login:{0}}}{{home:{0}}}".format(length)  # Un double {{ qui permet d'échapper le caractère '{'
     
    In [9]: template
    Out[9]: '{login:38}{home:38}'
     
    In [10]: for login in logins:                                                     
        print(template.format(login=login, home="/home/user/" + login))  # Pour le calcul du home, mieux vaut utiliser la fontion os.path.join
       ....:     
    login1                                /home/user/login1                     
    login111111                           /home/user/login111111                
    login78Y789909709898877777876868768   /home/user/login78Y789909709898877777876868768
    Edit: Je viens de voir que vous débutiez. Pour ouvrir un fichier, préconisez plutôt la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    with open('monfichier.txt') as f:
        mon_contenu = f.read()
    Le with permet de fermer le fichier quoi qu'il arrive. On peut imaginer que votre fichier disparaisse pendant que vous lisez/écrivez dedans ou toutes autres joies de la programmation et le with est là pour "sécuriser" votre code. Dans le cas présent, j'imagine que ce n'est pas un gros fichier. Mais si vous prenez gout à la programmation et que vous commencez à parser des gros fichiers avec des opérations plus ou moins critique, c'est une bonne habitude à prendre dès le début (et le with est utilisé très souvent pour les ouvertures/fermetures, pas seulement pour les fichiers, par la suite, vous risquez d'en rencontrer régulièrement).

    Bon courage !

  4. #4
    Membre régulier
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Janvier 2012
    Messages
    97
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2012
    Messages : 97
    Points : 75
    Points
    75
    Par défaut
    Merci de vos retour,

    En effet c'est quelques excercices dont je dois faire différentes versions pour voir à gerer les modules.

    Au final pour mon fichier psswd je suis revenu sur un for basique et pour la séparation le ljust avec le nombre de caractère +/- définit au plus gros login trouvé à suffit

    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
    #!/usr/bin/python2.6
    # -*- coding: utf-8 -*-
     
    chaine = "nologin" # Texte à rechercher
    psswd = file("/ccc/cont000/dsku/jade/home/user/erwtgcc/blanci/Bureau/passwd","r")
    passwd_extract=open("/ccc/cont000/dsku/jade/home/user/erwtgcc/blanci/Bureau/passwd_extract.txt","a")
     
    for aline in psswd:
        if chaine in aline:
            fields= aline.split( ":" )
          #  print fields[0], fields[5]
            line_new = fields[0].ljust(14)+fields[5].ljust(25)
            print line_new
            passwd_extract.write (line_new+'\n')
    print str("passwd_extract a été créé")
    passwd_extract.close()    
    psswd.close()

    Parcontre on me demande de le faire avec un module re à partir d'un retour de commande bash maintenant !

    la commande getent passwd me retourne tout à la suite séparé par des backslash, pour le moment j'en suis rendu ici, je me sert d'un grep nologin pour avoir directement les bonnes lignes à traiter dans mon retour de commande

    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
    #!/usr/bin/python2.6
    # -*- coding: utf-8 -*-
     
    #import subprocess,
    from subprocess import *
    import re
     
    #grep de nologin dans passwd
    cmd1 = Popen(['getent', 'passwd'],stdout=PIPE)
    cmd2 = Popen(['grep','nologin'],stdin=cmd1.stdout, stdout=PIPE)
    output = cmd2.communicate()
     
    #recherche et découpage entre 2 balises
    begin_balise = str("\\")
    end_balise = str("/nologin\\")
    motif = begin_balise + '.*' + end_balise
    obj_regex = re.search(motif,output)
    #boucle de split
    for aline in obj_regex:
        if obj_regex is None:
            print "aucun resultat trouve"
        else :
            fields= aline.split( ":" )
            print fields[0], fields[5]
    Le soucis est que mon retour n'est pas tres beau à mon avis le soucis d'utiliser un backslash en séparateur mais je ne voie pas quoi prendre d'autre avec le retour de ma commande:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [blanci@creteil Bureau]$ ./exo_call_shellcmd.py
    Traceback (most recent call last):
      File "./exo_call_shellcmd.py", line 16, in <module>
        obj_regex = re.search(motif,output)
      File "/usr/lib64/python2.6/re.py", line 142, in search
        return _compile(pattern, flags).search(string)
      File "/usr/lib64/python2.6/re.py", line 245, in _compile
        raise error, v # invalid expression
    sre_constants.error: bogus escape (end of line)
    [blanci@creteil Bureau]$
    J'ai regardé a le doubler le mettre entre crocher ou là, convertir en string il galère un peu et moi de même.

Discussions similaires

  1. Utilisation classe : problème de mise en page
    Par fafabzh6 dans le forum Mise en forme
    Réponses: 0
    Dernier message: 19/11/2010, 14h37
  2. Utiliser Flash pour la mise en page
    Par SoGood dans le forum Flash
    Réponses: 3
    Dernier message: 07/04/2009, 10h10
  3. Réponses: 5
    Dernier message: 08/03/2007, 17h14
  4. Quel logiciel utiliser pour mise en page
    Par sylsau dans le forum Applications et environnements graphiques
    Réponses: 10
    Dernier message: 11/07/2006, 13h06
  5. Réponses: 2
    Dernier message: 11/04/2006, 19h09

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