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 :

Récupérer une chaine inconnue entre deux chaines connues


Sujet :

Langage Perl

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 18
    Points : 13
    Points
    13
    Par défaut Récupérer une chaine inconnue entre deux chaines connues
    Bonjour,
    voila mon probleme je voudrais récupérer les colonnes entre le select et le from d'une requete sql de type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    REPLACE VIEW nomvue AS
         SELECT col1, col2,
         	col3 
         FROM ma table
         where col1>1
        ;
    Je ne sais pas comment regler ce probleme et je pense a deux pistes :
    - regarder ligne par ligne faire un split pour avoir tous les mots et enregistrer les mots jusqu'a avoir le second ce qui me parait lourd
    - voir le texte dans son ensemble et par une expression regulière bien sentie récupérer directement la chaine voulue, mais je n'arrive pas a trouver comment le réaliser!

    si vous avez des conseils ou d'autres propositions pour résoudre ce problème je suis tout ouïe!
    merci !

  2. #2
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    my $InFile = "P:/Perl/scripts/Files/test.txt";
    open (INFILE,"$InFile") or die "Can't open file\n";
    my @fich = <INFILE>;
    map {chomp($_)} @fich;
    my $Fich = join (" ", @fich);
    my ($colonnes) = ($Fich =~ /SELECT(.*)FROM/);
    print $colonnes;

    Jasmine,

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 18
    Points : 13
    Points
    13
    Par défaut
    ca marche nickel!
    merci jasmine t'es géniiiale

    je ne connaissait pas du tout le map pour faire le chomp sur le fichier.
    merci beaucoup donc

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 18
    Points : 13
    Points
    13
    Par défaut
    je tiens a rectifier ca ne marche pas tout a fait,

    dans le cas ou la requete contient un autre from (par exeemple si on travaille sur une union ou le cas d'une sous-requete) elle prend entre le premier select et le dernier from, or j'aimerais avec le premier from.

    je suppose qu'il faut regarder dans l'expression régulière pour ca, je vaiss essayer de creuser dans ce sens.

    ps : merci beaucoup beaucoup quand meme jasmine

  5. #5
    Membre confirmé
    Avatar de Schmorgluck
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2006
    Messages : 371
    Points : 558
    Points
    558
    Par défaut
    C'est parce que les quantificateurs classiques sont avides, et donc reconnaissent autant de texte que possible avant de passer la main. Du coup, s'il y a plusieurs occurrences de "FROM", elles seront toutes reconnues par .*, sauf la dernière que .* devra restituer pour que la reconnaissance marche.
    Il suffit donc de remplacer le quantificateur * par son équivalent paresseux, *?. Ce qui nous donne :
    Les quantificateurs paresseux (??,*?,+? et {a,b}?) ne reconnaissent du texte que si c'est indispensable, et donc la reconnaissance n'ira que jusque au premier FROM rencontré.

    Soit dit en passant, le SQL n'étant pas sensible à la casse en ce qui concerne ses commandes, peut-être serait-il avisé d'ajouter le modificateur i à la regex. De plus, surtout dans ce cas, pour éviter une erreur dans le cas où une table s'appelle "fromage" ou un truc du style, des ancres de limites de mots pourraient être utiles. Donc la regex pourrait ressembler à ceci :

  6. #6
    Expert éminent
    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
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par Jasmine80 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    my $InFile = "P:/Perl/scripts/Files/test.txt";
    open (INFILE,"$InFile") or die "Can't open file\n";
    my @fich = <INFILE>;
    map {chomp($_)} @fich;
    my $Fich = join (" ", @fich);
    Comme je le répète souvent, cette méthode n'est pas efficace : vous commencez par découper le fichier en le lisant ligne par ligne, puis vous oubliez toute cette information en mettant un join.

    Il est préférable de lire directement le fichier entier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    my $filename = 'P:/Perl/scripts/Files/test.txt';
    my $content = do { 
      local $/;
      open my($file), '<', $filename or die "Can't open $filename : $!\n";
      <$file>
    };
    my @select_columns = ($content =~  m/select (.+?) \b from \b /xgi);
    # éventuellement supprimer les retours chariots :
    map { tr/\n/ / } @select_columns;
    --
    Jedaï

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 18
    Points : 13
    Points
    13
    Par défaut
    merci beaucoup a tous,

    j'aimerais quelques explications supplémentaires sur l'expression régulière notemment sur le "/xgi" ou la doc perl et google n'arrivent pas a m'aider.

    De plus, le \b ne risque-t-il pas de me couper les nom de colonnes contenant un "_" ?

    merci pour tout le temps que vous m'accordez

  8. #8
    Expert éminent
    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
    Points : 8 586
    Points
    8 586
    Par défaut
    Citation Envoyé par unameno Voir le message
    j'aimerais quelques explications supplémentaires sur l'expression régulière notemment sur le "/xgi" ou la doc perl et google n'arrivent pas a m'aider.
    La doc Perl est très complète, presque trop parfois. Tu peux trouver toutes tes réponses dans perlre ou perlop. Pour faire court : avec /x, les espaces dans la regexp ne sont plus pris en compte, il faut écrire \s explicitement pour matcher un espace (plus exactement, un whitespace, une tabulation ou un passage à la ligne (\r ou \n)), ça permet d'espacer sa regexp pour la rendre plus lisible.
    avec /g on reconnait toutes les occurences d'une regexp, pas seulement la première, et en contexte de liste, comme ici, on renvoie la liste des captures.
    /i rend la regexp insensible à la casse.

    Citation Envoyé par unameno Voir le message
    De plus, le \b ne risque-t-il pas de me couper les nom de colonnes contenant un "_" ?
    Non, "_" est considéré comme un caractère de mot (reconnu par \w), donc "from_" n'est pas reconnu pas "from\b".

    --
    Jedaï

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 18
    Points : 13
    Points
    13
    Par défaut
    merci beaucoup Jedai !
    merci beaucoup a tous !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [RegEx] Récupérer du texte entre deux chaines de caractères
    Par Globolite dans le forum Langage
    Réponses: 3
    Dernier message: 10/07/2014, 16h38
  2. Réponses: 0
    Dernier message: 31/05/2011, 19h13
  3. Réponses: 1
    Dernier message: 16/10/2010, 17h50
  4. [RegEx] Récupérer une valeur entre deux chaines
    Par thebarbarius dans le forum Langage
    Réponses: 7
    Dernier message: 04/04/2010, 16h47
  5. [RegEx] Récupérer ce qu'il y a entre deux chaines (toute les occurences)
    Par greg1107 dans le forum Langage
    Réponses: 3
    Dernier message: 23/01/2008, 14h48

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