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 PHP Discussion :

Suite de lignes qui commencent par un même symbole ? [RegEx]


Sujet :

Langage PHP

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Novembre 2013
    Messages : 7
    Par défaut Suite de lignes qui commencent par un même symbole ?
    Bonjour/bonsoir,

    Je cherche à matcher une suite de lignes qui commencent par un même symbole, et stopper la regex dès qu'une nouvelle ligne commence par autre chose.

    Dans l'idée ça donnerait ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Texte
    *ligne
    *ligne
    *ligne
    Autre texte
    Encore du texte
    Et mon essai de regex, qui n'a pas fonctionné (je débute, ne pas rire trop fort ) :

    Merci à ceux qui pourront m'aider à y voir plus clair .

  2. #2
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Par défaut
    Je te propose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    preg_match('#(\*.+\r\n)+#', $text, $output);
    echo trim($output[0]);
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  3. #3
    Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Novembre 2013
    Messages : 7
    Par défaut
    Merci tu m'as sauvé de la folie . Cette regex fonctionne, mais je n'arrive pas à la comprendre ...
    J'ai un dernier souci, *ligne n'est pas match en fin de texte.

    Par exemple ceci :
    Texte
    Texte
    *ligne
    *ligne

    *dernier
    (fin)
    Va me donner :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    preg_match('#(\*.+\r\n)+#', $text, $output);
    print_r($output[0]);
     
    *ligne
    *ligne
    Je n'ai aucun autre souci ailleurs, que ce soit en début ou fin de texte .

  4. #4
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Par défaut
    Sinon comme ça, c'est peut etre mieux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    preg_match_all('#\*.+#', $text, $output);
    echo implode('', $output[0]);
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  5. #5
    Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Novembre 2013
    Messages : 7
    Par défaut
    Helas non ça s'éloigne de ce que je cherche à faire, car ça va tout regrouper dans le même array.

    Mais j'ai réussi à contourner le problème en ajoutant une ligne à la fin :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $text = $text . "\r\ntexte";
    // (...)
    $text = preg_replace_callback("#(\*.+\r\n)+#",makemealist,$text);
    $texte = str_replace("texte", "", $texte);
    return $texte;
    J'ai un dernier souci, ça ne vérifie pas si la ligne commence par une étoile. Donc ceci :
    texte*texte
    *ligne
    *ligne
    Tout va être match, alors que la première n'est pas en début de ligne. J'ai essayé de rajouter ^ au début mais ça ne fonctionne pas.

  6. #6
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Par défaut
    car ça va tout regrouper dans le même array.
    Je n'ai pas compris
    N'oubliez pas de consulter les FAQ PHP et les cours et tutoriels PHP

  7. #7
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php
    preg_match_all('#\r\n\*(.+)\r\n+#Ui', "\r\n".$text."\r\n", $output);
     
    //var_dump($output[1]);
     
    if(!empty($output[1])){
    	foreach($output[1] as $ligne){
    		echo trim($ligne).'<br />';
    	}
    }
    ?>
    $output[1] est un array contenant chaque ligne trouvée.

    Si on veut s'affranchir aussi des éventuelles tabulations ou espaces en début de lignes :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    preg_match_all('#\r\n[ \t]*\*(.*)\r\n#Ui', "\r\n".$text."\r\n", $output);
    Dernière modification par Invité ; 30/08/2015 à 17h20.

  8. #8
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 011
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 3 011
    Par défaut
    En utilisant le modificateur m l'ancre ^ matche le début de ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (preg_match_all('~^\*.*~m', $str, $matches))
        print_r($matches[0]);

  9. #9
    Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Novembre 2013
    Messages : 7
    Par défaut
    J'ai enfin trouvé la solution, après plusieurs dizaines de tentatives et une trentaine de tasses de café.

    C'est une regex du script Slimdown qui m'a mis sur la piste, il fallait rajouter un \n au début de la regex donnée par Sabotage.

    Mon script n'est pas parfait mais il fonctionne, merci ! Le voici en entier :
    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
    // /!\ Ce code répond à un besoin intermédiaire, celui de traiter chaque entrée de la liste à puces. /!\
    // /!\ Pour une simple conversion en liste voir le message de CosmoKnacki plus bas. /!\
     
    // Si la liste commence en début de string le premier élément sera ignoré, je contourne en rajoutant une ligne fictive
    $text = "line\n".$text;
    $text = preg_replace_callback("/(\n\*.+)+/",
    	function($liste){
    // Je découpe le tableau pour traiter chaque entrée de la liste à puces
    	$liste = preg_split("/\r\n/",$liste[0]);
    	foreach($liste as &$line){
    // Création des <li></li> et suppression de l'étoile
    		$line = "<li>".preg_replace("/\*/","",$line,1)."</li>";
    	}
    // Implode permet de regrouper tous les <li> avant de renvoyer la liste finale
    return "<ul>".implode("</li>", $liste)."</ul>";
    },$text);
    // Je supprime la ligne fictive
    $text = preg_replace("/^(?:line|line\n)/","",$text);
    Encore merci pour l'aide qui m'a été très précieuse, et en particulier à toi Sabotage car ta regex m'a servi de base pour le script final.

  10. #10
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    BRAVO pour ton usine à gaz !
    Elle me rappelle celles que je construisais moi-même....

    Tu devrais quand même prendre le temps de tester les codes qu'on te donne !
    Surtout celui du Maître es-regex CosmoKnacki (moi, je ne suis qu'un humble scarabée)

    Voici en 1 ligne ton résultat :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <?php
    $liste = (preg_match_all('~^\*([^\r]*)~m', $text, $output))? '<ul><li>'.implode('</li><li>', $output[1]).'</li></ul>' : '';
    ?>

    *ligne début
    Texte
    Texte
    *ligne 1
    *ligne 2
    Autre texte
    *ligne 3
    Encore du texte
    *ligne fin
    Renvoie :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    <ul><li>ligne début</li><li>ligne 1</li><li>ligne 2</li><li>ligne 3</li><li>ligne fin</li></ul>

    N.B. Si on veut améliorer l'indentation du code :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <?php
    $liste = (preg_match_all('~^\*([^\r]*)~m', $text, $output))? "<ul>\n<li>".implode("</li>\n<li>", $output[1])."</li>\n</ul>\n" : '';
    ?>
    Donne
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <ul>
    <li>ligne début</li>
    <li>ligne 1</li>
    <li>ligne 2</li>
    <li>ligne 3</li>
    <li>ligne fin</li>
    </ul>
    Dernière modification par Invité ; 01/09/2015 à 10h30.

  11. #11
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    3 011
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 3 011
    Par défaut
    moi, je ne suis qu'un humble scarabée
    Je viens juste de comprendre que le but recherché était de remplacer les listes en markup vers du html, je pense que Maître Po aurait été plus perspicace.

    On peut effectivement rechercher les bloc de lignes consécutives et utiliser preg_replace_callback:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $result = preg_replace_callback('~^\*([^\r\n]*(?:\R\*[^\r\n]*)*)~m', function ($m) {
        return '<ul><li>' . strtr($m[1], ["\r\n*"=>"</li><li>", "\n*"=>"</li><li>"]) . '</li></ul>';
    }, $text);
    Ce qui est la manière concise de le faire. Mais il est plus rapide de ne pas passer par les 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
    $nl = "\n"; // ou $nl = "\r\n";
    $inlist = false;
    $lines = explode($nl, $text);
    foreach ($lines as &$line) {
        if ($line && $line[0]=='*') {
            $line = ( $inlist ? '' : '<ul>' . $nl ) .'<li>' . substr($line, 1) . '<li>';
            $inlist = true;
        } elseif ($inlist) {
            $line = '</ul>' . $nl . $line;
            $inlist = false;
        }
    }
     
    $result = implode($nl, $lines);

    [Edit]

    En fait, la méthode avec preg_replace_callback peut être tout aussi rapide voire plus si le type de nouvelle ligne est fixé à l'avance ce qui permet d'utiliser str_replace qui n'aura qu'une seule passe à faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $nl = "\n";
    $result = preg_replace_callback('~^\*([^'.$nl.']*(?:'.$nl.'\*[^'.$nl.']*)*)~m', function ($m) use ($nl) {
        return '<ul><li>' . str_replace($nl . '*', '</li><li>', $m[1]) . '</li></ul>';
    }, $text);

  12. #12
    Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Novembre 2013
    Messages : 7
    Par défaut
    Citation Envoyé par jreaux62 Voir le message
    Bonjour,
    BRAVO pour ton usine à gaz !
    Elle me rappelle celles que je construisais moi-même....

    Tu devrais quand même prendre le temps de tester les codes qu'on te donne !
    Surtout celui du Maître es-regex CosmoKnacki (moi, je ne suis qu'un humble scarabée)
    Je te rassure, j'ai testé tous les codes mais aucun ne m'a donné satisfaction (comme l'a dit CosmoKnacki mon but n'était pas de tout regrouper mais bien de créer des listes à puces style markdown). Et j'ai en parallèle continué les recherches de mon côté pour comprendre davantage le fonctionnement des regex.

    Pour ce qui est de l'usine à gaz il est évident que je manque de recul sur le langage. Je ne pratique le PHP que depuis quelques semaines et mes scripts sont souvent inutilement longs alors qu'ils pourraient tenir en 3 lignes. Mais je ne reste pas sur mes acquis, et tout ce que j'apprends sera réutilisé pour améliorer mes scripts.

    Citation Envoyé par CosmoKnacki Voir le message
    [Edit]

    En fait, la méthode avec preg_replace_callback peut être tout aussi rapide voire plus si le type de nouvelle ligne est fixé à l'avance ce qui permet d'utiliser str_replace qui n'aura qu'une seule passe à faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $nl = "\n";
    $result = preg_replace_callback('~^\*([^'.$nl.']*(?:'.$nl.'\*[^'.$nl.']*)*)~m', function ($m) use ($nl) {
        return '<ul><li>' . str_replace($nl . '*', '</li><li>', $m[1]) . '</li></ul>';
    }, $text);
    Effectivement c'est beaucoup plus court.

    Mais mon code répond à un autre besoin, celui de pouvoir manipuler ultérieurement chaque élément de la liste à puces. C'est pour cette raison que j'ai tenu à tout regrouper dans un même array (mais comme dit plus haut je n'ai pas assez d'expérience, donc il doit évidemment exister un moyen plus simple pour concilier ton script avec mes besoins).

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 19/01/2011, 16h41
  2. Réponses: 1
    Dernier message: 30/09/2010, 11h34
  3. sed: remplacer une ligne qui commence par Version
    Par lili2704 dans le forum Linux
    Réponses: 8
    Dernier message: 21/07/2008, 15h26
  4. Réponses: 5
    Dernier message: 19/01/2007, 23h53
  5. Réponses: 6
    Dernier message: 08/07/2006, 13h07

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