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 :

Lire chaine longue and separer chiffres et lettres [RegEx]


Sujet :

Langage PHP

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2013
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Décembre 2013
    Messages : 49
    Points : 39
    Points
    39
    Par défaut Lire chaine longue and separer chiffres et lettres
    Bonjour à tous.

    Je voudrais lire des chaines longues comme cela:
    1 Cuando a los pocos días volvió Jesús a Cafarnaún, se supo que estaba en casa*. 2 Acudieron tantos que no quedaba sitio ni a la puerta. Y les proponía la palabra. 3 Y vinieron trayéndole un paralítico llevado entre cuatro 4 y, como no podían presentárselo por el gentío, levantaron la techumbre encima de donde él estaba, abrieron un boquete y descolgaron la camilla donde yacía el paralítico. 5 Viendo Jesús la fe que tenían, le dice al paralítico: «Hijo, tus pecados te son perdonados». 6 Unos escribas, que estaban allí sentados, pensaban para sus adentros: 7 «¿Por qué habla este así? Blasfema. ¿Quién puede perdonar pecados, sino solo uno, Dios?». 8 Jesús se dio cuenta enseguida de lo que pensaban y les dijo: «¿Por qué pensáis eso? 9 ¿Qué es más fácil, decir al paralítico: “Tus pecados te son perdonados”, o decir: “Levántate, coge la camilla y echa a andar”? 10 Pues, para que veáis que el Hijo del hombre tiene autoridad en la tierra para perdonar pecados —dice al paralítico—: 11 “Te digo: levántate, coge tu camilla y vete a tu casa”». 12 Se levantó, cogió inmediatamente la camilla y salió a la vista de todos. Se quedaron atónitos y daban gloria a Dios, diciendo: «Nunca hemos visto una cosa igual».
    Je voudrais donc séparer les chiffres et le texte pour associer dans un array le nombre de gauche au texte complet de droite jusqu'au nombre suivant pour après insérer ces valeurs dans une base de données.

    J'ai réussi faire cela:
    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
     
    	$matches = preg_split('/[0-9]+/', $chaine_longue);
    	$sql = array();
    	foreach($matches as $key => $value){
    		$$key = $value;
    		$value=nl2br2($value);
    		$value=trim($value);
    		if ($key==0){
    			} else {
    			$key = (int)$key;
    			$sql[] = '('.$libro.', '.$capitulo.','.$key.',"'.$value.'")';
    			print_r($key.' '.$value);
    		}
    	}
    	$mysql_query='INSERT INTO tblBibliaCEE (libro,capitulo, versiculo, texto) VALUES '.implode(',', $sql);
    Ca marche parfaitement lorsque les chiffres de gauche commencent par 1 et s'augmentent par 1 à chaque fois, mais je voudrais que la variable $key prenne à chaque fois le nombre qui rencontrerait a gauche car ce n'est pas toujours que ma chaine a du texte commençant par un.

    Merci d'avance si quelqu'un peut me donner des idées.

  2. #2
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Points : 16 372
    Points
    16 372
    Par défaut
    Je dirais que le flag PREG_SPLIT_DELIM_CAPTURE a l'air fait pour toi :
    PREG_SPLIT_DELIM_CAPTURE
    Si cette option est activée, les expressions entre parenthèses entre les délimiteurs de masques seront aussi capturées et retournées.
    Essaye quelque chose comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $matches = preg_split('/([0-9]+)/', $chaine_longue, -1, PREG_SPLIT_DELIM_CAPTURE);
    $nbMatches = count($matches);
    for (int $i = 0; $i < $nbMatches; $i = $i+2;) {
    	$verse = $matches[$i];
    	$texte = $matches[$i+1];
    	// ...
    	$sql[] = '('.$libro.', '.$capitulo.','.$verse.',"'.$texte.'")';
    }
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2013
    Messages
    49
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Décembre 2013
    Messages : 49
    Points : 39
    Points
    39
    Par défaut
    Grand merci Celira,

    C'était juste cela dont j'avais besoin.

    Mais j'ai du corriger deux choses: mettre entre parentheses le (int) e initializer $i avec 1 et non 0 Je partage le code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    $matches = preg_split('/([0-9]+)/', $ab, -1, PREG_SPLIT_DELIM_CAPTURE);
    $nbMatches = count($matches);
    for ((int) $i = 1; $i < $nbMatches; $i = $i+2) {
    	$verse = $matches[$i];
    	$texte = $matches[$i+1];
    	echo $verse.' '.$texte.'<br />';
    	// ...
    	$sql[] = '('.$libro.', '.$capitulo.','.$verse.',"'.$texte.'")';
    }
    Encore merci. C'est résolu.

  4. #4
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Points : 16 372
    Points
    16 372
    Par défaut
    C'est l’inconvénient d'écrire le code à la volée sur le forum : ça ne fonctionne pas toujours exactement comme prévu , mais si ça donne une base de travail et qu'au final, le script fonctionne, c'est l'essentiel

    Si c'est résolu, un p'tit clic sur
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

  5. #5
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Moi, je l'aurais plutôt fait en récupérant le verset complet et en capturant le numéro avec preg_match_all:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $result = [];
     
    if (preg_match_all('~\G\s*(\d+)\s+\K\D+[^\s\d]~', $ab, $matches, PREG_SET_ORDER)) {
        foreach ($matches as $m) {
            $result[$m[1]] = $m[0];
        }
    }
     
    print_r($result);
    Détails de la pattern:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ~       # délimiteur
    \G      # ancre pour le début de la chaîne ou pour la fin du résultat précédent.
            # c'est pour s'assurer que les résultats sont contigus et ça permet d'ancrer la pattern
    \s*     # espaces éventuels (il n'y en a pas pour le premier verset)
    (\d+)   # on capture le numéro du verset dans le groupe 1
    \s+     # espaces
    \K      # on enlève tout ce qui précède du résultat du match
    \D+     # pour ne garder que le texte
    [^\s\d] # que l'on trim à droite en interdisant que le dernier caractère soit un espace.
    ~
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  6. #6
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Points : 16 372
    Points
    16 372
    Par défaut
    Là, tu dépasses largement mon niveau en regex : je connaissais pas la moitié des choses que tu utilises. En tout cas, c'est toujours bon à connaitre.
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

  7. #7
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    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 : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    N'exagérons rien, c'est vrai que \G et \K ne sont pas forcément très connus du fait principalement qu'ils ne sont pas toujours disponibles, (Tous les langages utilisant la syntaxe ECMA script ou POSIX, Python, et Java(*) et .net(*) uniquement pour \K.). Ou dans d'autre cas, parce que leur l'implémentation est relativement récente (En Ruby \K n'est disponible que depuis la version 2.0). Mais il n'y a pas beaucoup de monde qui connait l'existence de PREG_SPLIT_DELIM_CAPTURE (voire même qui ont poussé la curiosité au delà du deuxième paramètre de preg_split).

    \K est vraiment simple à utiliser et apporte une grande souplesse (dans l'exemple précédent il évite la création d'un groupe de capture). Il permet également de résoudre dans la plupart des cas le problème du test arrière (lookbehind) de longueur variable (on ne peut pas écrire (?<=ab+c)d(*) par contre on peut écrire ab+c\Kd). Les caractères enlevés à gauche du résultat sont quand même consommés par la pattern (le pointeur continue à avancer dans la chaîne).

    En ce qui concerne le \G c'est une ancre au même titre que ^ sauf qu'il marque la position suivant la dernière correspondance (donc au démarrage, il est marque le début de la chaîne, puis la position après la première correspondance, etc. ). Il permet d'assurer que les correspondances sont à la queue leu leu.
    Son utilisation permet par exemple d'obtenir des correspondances uniquement entre deux bornes avec une seule pattern (par exemple chaque mots dans une parenthèse et pas ceux en dehors) ou bien de vérifier le format d'une chaîne de bout en bout tout en extrayant un nombre indéterminé d'éléments.
    Ceci dit il n'est pas toujours facile de le mettre en œuvre au début.

    Dans la pattern précédente cette ancre n'est utile que pour la première correspondance en provoquant l'arrêt immédiat des hostilités si aucun chiffre n'est trouvé. Elle est devient inutile pour les recherches suivantes mais ne les gênera pas.

    (*) À noter que ces deux langages ont par ailleurs la possibilité d'avoir des lookbehind de longueur variable. Limité (et pas mal bugué) pour Java (on peut écrire (?<=a.{1,1000})b par exemple), illimité pour .net. PHP quant à lui ne peut se cantonner qu'à des alternatives de tailles fixes: (?<=ab|abc|abcd).
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

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

Discussions similaires

  1. expression reguliere separer chiffre et lettre
    Par nico38100 dans le forum Langage
    Réponses: 7
    Dernier message: 12/03/2013, 17h17
  2. Convertir des chaines de caratères en chiffres
    Par Mr Hyde dans le forum Général Python
    Réponses: 1
    Dernier message: 06/09/2005, 15h18
  3. [VB.NET] Import donnes d'excel : chiffres et lettres
    Par JohnGT dans le forum Windows Forms
    Réponses: 5
    Dernier message: 19/10/2004, 18h53
  4. Réponses: 4
    Dernier message: 21/07/2004, 10h51

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