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

Langage Perl Discussion :

problème : Traitement d'une chaine


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Inscrit en
    Novembre 2005
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5
    Par défaut problème : Traitement d'une chaine
    Bonjour,

    voila mon problème : j'ai une chaine de caractère :
    B.TOTO, C.TA_TA, SUBSTR(A.TUTU,1,4)!!'-'!!SUBSTR(A.TETE,5,2)!!'-'!!SUBSTR(A.TYTY,7,1),B.TITI
    et j'aimerai la couper au niveau des "," de façon à récupérer dans un tableau :

    B.TOTO
    C.TA_TA
    SUBSTR(A.TUTU,1,4)!!'-'!!SUBSTR(A.TETE,5,2)!!'-'!!SUBSTR(A.TYTY,7,1)
    B.TITI

    mon problème c'est que la fonction split sépare même au niveau des virgules dans les parenthèses ce que je ne veux pas ...
    j'ai beau chercher je ne vois pas comment faire pouvez vous m'aider s'il vous plait ?

    merci.

  2. #2
    Membre Expert Avatar de MarneusCalgarXP
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    911
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 911
    Par défaut
    question : y a-t-il un espace après chaque virgule que tu veux utiliser comme séparateur ?

  3. #3
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Citation Envoyé par MarneusCalgarXP
    question : y a-t-il un espace après chaque virgule que tu veux utiliser comme séparateur ?
    Pas dans son exemple...

    --
    Jedaï

  4. #4
    Futur Membre du Club
    Inscrit en
    Novembre 2005
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5
    Par défaut
    @ MarneusCalgarXP : Non, il peut y avoir un espace comme il peut ne pas y en avoir et il en va de même dans les parenthèses.

    @ Jedai : Non il peut très bien y avoir SUBSTR(SUBSTR(A.TUTU,1,4),5,10) ...

    PS: A noter que dans la parenthèse on peut aussi trouver MAX(TO_TO,TUTU), la virgule à l'intérieur d'une parenthèse n'est pas forcément suivi d'un chiffre

    PS2: Les fonctions sont fausses bien entendu mais c'est à titre d'exemple ...

  5. #5
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Citation Envoyé par hitsugaya
    @ Jedai : Non il peut très bien y avoir SUBSTR(SUBSTR(A.TUTU,1,4),5,10) ...
    Désolé, mais dans ce cas ton problème est trop complexe pour de vraies regex (ton langage n'est pas régulier), il pourrait être réglé avec les regex de Perl, mais je te le déconseille car la complexité nécessaire rendra ton programme difficile à comprendre... Perl 5.10 permettra de faire ça bien plus facilement.
    Mieux vaut écrire un véritable Parser pour l'instant. Par exemple avec Parse::RecDescent :
    Code Perl : 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/perl
    use strict; use warnings;
     
    use Parse::RecDescent;
     
    my $grammar = q {
    line: statement(s /, */) /\n?/      { $return = [ @{$item[1]} ] }
     
    statement: expr(s)                   { $return = join '', @{$item[1]} }
     
    expr: notcomma paren(?)              { $return = @{$item[2]} ? $item[1].$item[2][0] : $item[1] }
     
    paren: '(' expr(s? /,/) ')'          { $return = '('.(join ',', @{$item[2]}).')' }
     
    notcomma: /[^,()\n]+/
    };
     
    my $text = "B.TOTO, C.TA_TA, SUBSTR(SUBSTR(A.TUTU,1,4),1,4)!!'-'!!SUBSTR(A.TETE,5,2)!!'-'!!SUBSTR(A.TYTY,7,1),B.TITI\n";
     
    my $parser = Parse::RecDescent->new($grammar) or die "Bad grammar!\n";
     
    defined( my $ret = $parser->line($text) ) or die "Bad text!\n";
     
    __END__

    --
    Jedaï

  6. #6
    Membre Expert Avatar de MarneusCalgarXP
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    911
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 911
    Par défaut
    Citation Envoyé par Jedai
    Pas dans son exemple...
    C'est la raison pour laquelle je lui demandais, au cas où il s'agirait d'un problème de copier coller pour l'exemple...

  7. #7
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Citation Envoyé par MarneusCalgarXP
    C'est la raison pour laquelle je lui demandais, au cas où il s'agirait d'un problème de copier coller pour l'exemple...
    C'eut été une bénédiction !

    La solution avec regex :
    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
    use re 'eval';
    my $expr;
    $expr = qr{
    [^,()\n]+
    (?:
      \( 
        (?:
          (?> [^,()]+ )
        | (??{ $expr })
        )?
        (?:
          (?> ,[^,()]+ )
        | (,??{ $expr })
        )*
      \)
    )?
    }x;
     
    my $statement = qr{$expr*};
     
    my @line;
    $text =~ m/($statement)/g;
    my $first = $1;
    push @line, $first;
    while( $text =~ m/\G, *($statement)/g ) {
        push @line, $1;
    }
    A vous de voir quel est la plus simple et la plus maintenable (sans parler du fait que (?? { }) n'est pas très très stable je crois).

    --
    Jedaï

  8. #8
    Futur Membre du Club
    Inscrit en
    Novembre 2005
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5
    Par défaut
    Merci pour l'aide !!

    Entre temps j'ai réussi à trouver une feinte (idiote mais bon ca marche quand même ) pour faire ce que je voulais. Je la mets au cas où quelqu'un aurait le même problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    my $separateur = "§";
     
    $cpt = 0;
    for(0..length($texte)){
    	$cpt++ if((substr($texte,$_,1) eq "(")==1);
    	$cpt-- if((substr($texte,$_,1) eq ")")==1);
     
            if((substr($texte,$_,1) eq ",")==1 and $cpt == 0){
    	        $texte = substr($texte,0,$_) . $separateur . substr($texte,$_+1, length($texte));
            }
    }
    En fait c'est tout bête, je comptabilise dans $cpt le nombre de parenthèse ouvrante rencontrées, je décrémente $cpt quand je rencontre une parenthèse fermante. Et je "remplace" la virgule lorsque j'en rencontre une et que $cpt est à 0.

    Vila ça à l'air de marcher ... (j'ai pas rencontré d'erreur pour l'instant -Croise les doigts ^^ - )

    Encore merci à vous pour m'avoir aidez bye

  9. #9
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    C'est une bonne solution algorithmiquement parlant, j'avais envisagé d'en parler avant pour t'en dissuader, parce qu'en Perl pur implémenter cette solution est particulièrement lent... surtout si comme toi on mets des substr() partout.
    Par ailleurs cette solution ne te protège pas des parenthésages incorrects (tu devrais vérifier que $cpt ne devient pas négatif, et te plaindre dans ce cas).

    Au moins utilise une variable temporaire et évite les "(_ eq _) == 1" inutiles :
    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
        my $in = 0;
        my @line;
        my $start = 0;
        for(0..length($text) - 1){
            my $char = substr $text, $_, 1;
            $in++ if $char eq '(';
            $in-- if $char eq ')';
            die "Parenthésage incorrect\n" if $in < 0;
     
                if( $char eq ',' and not $in){
                    push @line, substr $text, $start, $_ - $start;
                    $start = $_ + 1;
                }
        }
        push @line, substr $text, $start;
     
    # si tu veux récupérer ta ligne avec de nouveaux séparateur :
    my $newline = join '§', @line;
    --
    Jedaï

  10. #10
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Peux-tu nous garantir qu'il n'y aura qu'un seul niveau de parenthèse au plus ?

    --
    Jedaï

Discussions similaires

  1. [FLASH 8] traitement d'une chaine de caractère
    Par KaiN_974 dans le forum Flash
    Réponses: 17
    Dernier message: 12/06/2006, 11h42
  2. Réponses: 2
    Dernier message: 21/12/2005, 16h23
  3. Traitement d'une chaine
    Par Kerod dans le forum Langage
    Réponses: 9
    Dernier message: 11/09/2005, 00h55
  4. traitement d'une chaine de caractère
    Par mohamed dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 09/12/2004, 17h45
  5. Réponses: 3
    Dernier message: 21/06/2004, 11h20

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