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

Linux Discussion :

[Sed & regex] Challenge pour les meilleurs d'entre vous!


Sujet :

Linux

  1. #1
    Invité
    Invité(e)
    Par défaut [Sed & regex] Challenge pour les meilleurs d'entre vous!
    Bonjour tout le monde,


    Voilà, j'ai eu un petit casse-tête à résoudre (que je me suis infligé ). C'est du parsing, donc je me disais qu'une regex ferait l'affaire.

    Et bien j'ai eu beau tourner le problème dans tous les sens, je n'y suis pas parvenu avec une regex unique, alors je me suis débrouillé autrement. Ma solution est moins bonne, moins belle et moins efficiente que celle que j'espérais, mais ça marche.

    Alors j'aimerais savoir s'il y en a ici qui seraient capables de le résoudre. Moi, ça me paraît impossible, et j'aimerais savoir si j'ai tort.

    Rentrons dans le vif du sujet: j'ai une liste de fichiers qui suivent une convention de nommage assez "flexible" disons (liste écrite dans un fichier texte).


    La voici, les crochets représentant les choses facultatives

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    date[ - type_depense] - description_depense[ - depense]extension
    Voici les regex correspondant aux différents éléments:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    jour="[0-9]{2}"
    mois="[0-9]{2}"
    annee="[0-9]{4}|[0-9]{2}"
    separateur_date="[-:.]"
    date="($jour)$separateur_date($mois)$separateur_date($annee)"
    type_depense="(Perso|Professionnelle)"
    description_depense="(.*)"
    montant="[0-9]+,[0-9]{1,2}"
    devise=" ?[a-zA-Z]{3}"
    depense="($montant)($devise)?"
    extension="\.[a-zA-Z0-9]{3,4}"
    Quelques exemples d'entrées valides:
    23:02:09 - Professionnelle - Ma description - 43,06EUR.png
    23-02-09 - Perso - Ma-description - 43,06 EUR.png
    23.02.2009 - Professionnelle - Une autre desciption - 43,06.jpg
    23:02:09 - Description - 43,06.pdf
    23-02-09 - Une-dernière-description.gif

    Le challenge est d'extraire les informations utiles: le jour, le mois, l'année, le type de dépense, la description, le montant et la devise et de les mettre dans un fichier CSV (fichier texte où chaque élément utile de chaque ligne est placé entre des point-virgules).

    [Edit] Oubli qui a son importance: le type de dépense et la description doivent être mis entre guillemets dans le fichier CSV. D'autre part, la date doit être formatée comme suit: jour/mois/année

    MAIS, et c'est ici que ça se corse, en utilisant une seule regex et une seule fois sed (ou un autre programme utilisant les regex POSIX). Pour ceux qui ont l'habitude des regex, le vrai challenge est de se passer des qualificateurs non gourmands et des assertions, et plus généralement de tout ce qu'on retrouve dans les PCRE mais pas dans les regex POSIX.


    Voilà, moi je n'y suis pas parvenu et j'ai dû "tricher" en remplaçant d'abord le séparateur " - " par un séparateur à un seul caractère (le point virgule) et en utilisant une classe d'exclusion (description_depense devient "[^;]+").


    Alors, si quelqu'un parvient à résoudre ce problème, il aura… toute mon admiration, car pour moi c'est un problème impossible à résoudre avec les regex POSIX.


    Bon courage et bonne chance à ceux qui voudront relever le challenge.


    PS: s'il faut y'a une solution toute simple à laquelle je n'ai pas pensé et je vais passer pour un débile, mais bon tant pis
    Dernière modification par Invité ; 28/04/2009 à 12h01.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 587
    Points : 19 467
    Points
    19 467
    Par défaut
    Bonjour,

    Tu obtiens donc un fichier tel que

    23;02;09;Professionnelle;Ma description;43,06;EUR;png;
    23;02;09;Perso;Ma-description;43,06;;EUR;png;
    23;02;09;Professionnelle;Une autre desciption;43,06;;jpg;
    23;02;09;;Description;43,06;;pdf;
    23;02;09;;Une-dernière-description;;gif;

    c'est à dire, dans lequel, si un élément est absent du fichier original, cet élément est "remplacé" par un point virgule...

    Tu confirmes ?

    --
    de mon côté, pour l'instant, j'en suis encore là :
    -> ->

  3. #3
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    Bonjour,

    Tu obtiens donc un fichier tel que

    23;02;09;Professionnelle;Ma description;43,06;EUR;png;
    23;02;09;Perso;Ma-description;43,06;;EUR;png;
    23;02;09;Professionnelle;Une autre desciption;43,06;;jpg;
    23;02;09;;Description;43,06;;pdf;
    23;02;09;;Une-dernière-description;;gif;

    c'est à dire, dans lequel, si un élément est absent du fichier original, cet élément est "remplacé" par un point virgule...

    Tu confirmes ?

    --
    de mon côté, pour l'instant, j'en suis encore là :
    -> ->
    Oui. Sauf, que je ne conserve pas l'extension et que je rajoute des guillemets là où il faut (description et type de dépense), mais bon, c'est du détail.

    Tu as trouvé?


    [Edit] Je crois savoir ce que tu as fait, et ce que je disais n'est peut-être plus du détail: il faut mettre entre guillemets la description et le type de dépense.

    [Edit 2] Et un autre truc que je n'avais pas vu: la date doit formatée comme suis: jour/mois/année

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 587
    Points : 19 467
    Points
    19 467
    Par défaut
    Citation Envoyé par Mateo34
    Tu as trouvé?
    Non, non, loin de là... -> ->

    Je ne parviens pas encore à me figurer comment tenir compte d'un élément qui est absent, pour quand même faire un ajout (par exemple, si perso, ou professionnelle, n'est pas là, il faut tout de même ajouter un point-virgule)...

    Ah si ! Attend,... bah non.
    Presque, mais pas encore.

    désolé.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    Non, non, loin de là... -> ->

    Je ne parviens pas encore à me figurer comment tenir compte d'un élément qui est absent, pour quand même faire un ajout (par exemple, si perso, ou professionnelle, n'est pas là, il faut tout de même ajouter un point-virgule)...

    désolé.


    Bon, si ça peut aider, voilà en gros l'expression régulière (fausse):
    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
     
    separator=" - "
    day="[0-9]{2}"
    month="[0-9]{2}"
    year="[0-9]{4}|[0-9]{2}"
    dateSeparator="[-:.]"
    date="($day)$dateSeparator($month)$dateSeparator($year)"
    expenseType="Lunch|Other"
    expenseDescription=".*"
    expenseAmount="[0-9]+,[0-9]{1,2}"
    expenseCurrency=" ?[a-zA-Z]{3}"
    expense="($expenseAmount)($expenseCurrency)?"
    extension="\.[a-zA-Z0-9]{3,4}"
     
    regexp="^$date($separator($expenseType))?$separator($expenseDescription)($separator$expense)?$extension$"
    Et ce par quoi on le remplace:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    replacement="\1\/\2\/\3;\"\5\";\"\6\";\8;\9"

    L'expression régulière est "fausse" car le quantificateur * est "gourmand" c'est-à-dire en gros qu'il ne prend pas le séquence trouvée la plus courte mais la plus longue.
    Avec les PCRE, on règle ce problème en passant le * en quantificateur non gourmand à l'aide du point d'interrogation: *?
    Avec les PCRE, on peut aussi utiliser les assertions. Dans notre cas, on aurait utilisé l'assertion avant négative: (?!motif), ce qui aurait donc donné .*(?! - ).

    Mais malheur de malheur sed ne connaît que les regex POSIX, pas les PCRE. Et ce nul n'est pas capable de stocker plus de 9 buffers, au passage…

Discussions similaires

  1. Réponses: 0
    Dernier message: 15/07/2014, 21h31
  2. Conseil clé primaire pour les meilleurs performances ?
    Par ites dans le forum Optimisations
    Réponses: 23
    Dernier message: 04/07/2008, 10h36
  3. Challenge pour les insomniaques
    Par LEK dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 02/05/2008, 00h42
  4. Taille du transaction.log pour les meilleures performances
    Par Tartenpion dans le forum MS SQL Server
    Réponses: 8
    Dernier message: 25/10/2006, 14h52

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