11485 sujets

JavaScript, DOM et API Web HTML5

Bonsoir à tous
Je cherche à découper une chaîne de caractères en "fractions".
Le texte d'entrée est
Ceci est une @#tuilette1, suivie d'une @#tuilette2 et d'autres babioles.

Je voudrais obtenir un tableau contenant:

["Ceci est une ", "@#tuilette1", ", suivie d'une ", "@#tuilette2", " et d'autres babioles."]

Je n'arrive pas à faire la rexexp qui me donne ce résultat.
Mon dernier essai (toujours infructueux):
var valueParts = itemValue.match(/(^.*?)(@#[A-za-z0-9_-]*|$)/g);

Merci de votre aide
Bonsoir PapyJP,
Il vous faut utiliser la fonction split, avec comme critère les @#machin :
var valueParts=itemValue.split(/(@#[a-zA-Z0-9_-]+)/g)

Les parenthèses font que les captures sont conservées dans le résultat.
++
Merci pour cette réponse, ça marche très bien.
Je n'avais jamais vu utiliser split avec des parenthèses, on en apprend toujours de nouvelles en s'adressant à des gens compétents!
Je ferai plus de tests demain, mais cela me semble ouvrir la voie vers ce que je recherche.
En regardant la documentation sur la méthode split(), je trouve dans ce document une phrase inquiétante:
MDN a écrit :
Si le séparateur est une expression rationnelle qui contient des parenthèses groupantes, à chaque fois que le séparateur correspond, les résultats (incluant tout résultat indéfini) des groupes iront dans le tableau retourné. Cependant, tous les navigateurs ne supportent pas cette possibilité.

Sait on quels sont les navigateurs qui ne supportent pas cette possibilité?
Je suppose que, comme d'habitude, les vieilles versions de IE font partie du lot, mais ce n'est pas clair.
Auriez vous une proposition de solution alternative?
Hmm!
L'article a beau dater de 2011, celui que j'ai trouvé sur MDN date du mois dernier, j'ai donc tendance à penser que le problème n'est pas complètement réglé.
Je pense que je vais faire un contournement, du genre:

itemValue = itemValue.replace(/(@#[A-Za-z0-9_-]*)/g, '%%$1%%');
itemParts = itemValue.split('%%');

Un peu lourdingue, mais ça devrait marcher, je pense.
Bonjour,
Je n'ai pas souvent utilisé split dans ces conditions, je ne connais pas vraiment son support.
Une solution "fiable" serait, je pense, de faire en 3 étapes :
- faire un split sans les captures pour n'obtenir que le texte -> array1
- faire un match pour capturer les @#[\w-] -> array2
- faire une petite boucle qui remplit alternativement un tableau avec array1 et array2
Vous avez 2h Smiley lol
var itemValue = 'Ceci est une @#tuilette1, suivie d\'une @#tuilette2 et d\'autres babioles.';
var array1 = itemValue.split(/@#[^\s]+/);
var array2 = itemValue.match(/@#[^\s]+/g);
var resultat = [];
resultat.push(array1[0]);
var i = 0;
if (array2) // S'il y avait des tuilettes...
    {
    var c = array2.length;
    while(i < c)
        {
        resultat.push(array2[i]);
        resultat.push(array1[i+1]);
        i++;
        }  
    }

console.log('Resultat : ' + resultat);


La solution de Papy est-elle si peu satisfaisante ?

Smiley smile
Modifié par Zelena (30 Mar 2017 - 19:59)
Elle est bien mais il y aura toujours un puriste pour dire "oui mais si la chaîne contient un '%' ?" Ok, t'en mets deux... "oui mais si elle en contient 2 ?" Ben t'en mets 50, ça doit être rare les chaînes avec 50 caractères % à la suite... "rare mais pas impo..." PAN !
Smiley biggol
Humh... en dehors des exercices de frappe sur clavier, je suis à peu près sûre de n'avoir jamais rencontré plusieurs '%' consécutifs... Peut-être sur du code informatique.

Enfin nul ne sait mieux que PapyJP ce qu'il y a dans ces chaînes de caractères...

Smiley smile
PapyJP a écrit :
Bonsoir à tous
Je cherche à découper une chaîne de caractères en "fractions".
Le texte d'entrée est
Ceci est une @#tuilette1, suivie d'une @#tuilette2 et d'autres babioles.

Je voudrais obtenir un tableau contenant:

["Ceci est une ", "@#tuilette1", ", suivie d'une ", "@#tuilette2", " et d'autres babioles."]

Je n'arrive pas à faire la rexexp qui me donne ce résultat.
Mon dernier essai (toujours infructueux):
var valueParts = itemValue.match(/(^.*?)(@#[A-za-z0-9_-]*|$)/g);

Merci de votre aide

Suis pas spécialiste de PHP, aussi me suis-je dis que cela pourrait être intéressant à titre d'exercice commenté Smiley biggrin .
A priori, je ne recours pas aux expressions régulières, et préfère procéder comme je le fais en Java, c'est à dire à la mano et de façon rustique. C'est brut, pas beau, mais portable et on ne se casse pas la tête avec les spécificités des expressions régulières. Une seule expression est utilisée, pour identifier les mots clés. Le reste, c'est du découpage de texte en petits bouts transférés dans un tableau.
Le code PHP ci-après n'est par conséquent ni génial, ni optimisé, et peut-être ne fonctionne-t-il pas dans tous les cas. Je le mets toutefois ici pour voir s'il tient la route et soulève, sinon l'enthousiasme, du moins les critiques (forcément constructives, hein...).
<?php

function split($input,$pattern)
{

	// Initialisation du tableau récupéré en sortie

	$output = [];

	// Tant que le tampon n'est pas null ou vide

	while (is_null($input) ? false : strlen($input) > 0)
	{
		
		// Recherche du prochain mot clé
		
		preg_match(PATTERN,$input, $matches, PREG_OFFSET_CAPTURE);
		
		// Test dimension tableau contenant le résultat de la recherche
		// [0] -> Mot clé récupéré
		// [1] -> Position du mot clé dans le tampon dans un domaine 0..N-1
		
		$size = is_null($matches) ? 0 : count($matches);
		
		// Traitement différencié selon résultat recherche mot clé
		
		switch ($size)
		{
		case 0 :
			{
				
			// Le tampon ne contient aucun mot clé
			// -> ajout du tampon dans le tableau en sortie
			// -> réinitialisation du tampon en tant que chaîne vide (fin de traitement)
		
			array_push($output,$input);
				
			$input = '';
			
			break;
				
			}
		case 1 :
			{
				
			// Le tampon contient au moins un mot clé
			// -> récupération du mot clé trouvé
			// -> récupération de la position du mot clé dans le tampon
			// -> récupération de la partie éventuellement située avant le mot clé dans le tampon
			
			$token = $matches[0][0];
			$offset = $matches[0][1];
			
			// Un peu de parano...
			
			if ($offset < 0) throw new Exception("Unexpected offset value");
			
			$part = $offset > 0 ? substr($input,0,$offset) : '';
			
			// Ajout dans le tableau en sortie de la partie avant mot clé si non nulle ou vide
			
			if ((is_null($part) ? 0 : strlen($part)) > 0)
			{
			
				array_push($output,$part);
				
			}
			
			array_push($output,$token);
			
			// Suppression de la partie avant (si existe) + mot clé dans le tampon

			$input = substr($input,$offset + strlen($token));
		   
			break;
				
			}
		default :
			{
				
			// Erreur 
				
			throw new Exception('Too many tokens found.');
				
			}
		}    

	}
	
	return $output;

}

	// Expression régulière à utiliser pour extraire les mots clés

	const PATTERN = '/@#tuilette\d{1,5}/';

	// Initialisation de la chaîne alphanumérique en entrée

	$text = 'Ceci est une @#tuilette1, suivie d\'une @#tuilette2 et d\'autres babioles.';
	
	$parts = split($text,PATTERN);

	print_r($parts); 

?>

J'ai posé comme postulat qu'il n'y aurait pas plus de 5 chiffres en fin de mot clé, mais l'expression peut bien entendu être adaptée si cette valeur s'avère être supérieure.
Ci-dessous le résultat obtenu sur un éditeur PHP en ligne :
Array ( [0] => Ceci est une [1] => @#tuilette1 [2] => , suivie d'une [3] => @#tuilette2 [4] => et d'autres babioles. ) 

Voilà, voilà...
Pas le temps de tester tous les cas de figure, mais si certains veulent s'amuser avec et constatent des erreurs, les retours seront appréciés.
Merci d'avance.
Modifié par sepecat (30 Mar 2017 - 22:53)
Merci de vos réponses
Le propriétaire du site m'a demandé
Thierry a écrit :

Une idée serait de pouvoir avoir systématiquement une définition et/ou explication avec certains mots:
par exemple, si je tape @#dieuwxyz, le mot dans le texte est relié au même objet, en l’occurrence une courte présentation du dieuwxyz (étant bien sûr entendu que si je tape le nom sans @# devant, il reste normal).

C'est pour réaliser cette fonction que j'ai regardé comment analyser le contenu d'une balise <p> (en fait je le fais pour tous les childNodes de la balise <p>) pour trouver des "mots clés", et c'est en faisant cette recherche que je suis tombé sur ce problème.

Je ne sais pas encore très bien ce qu'il veut utiliser comme mots-clés, donc la syntaxe @#tuilette2 est purement bidon, je ne peux pas me baser la dessus pour faire le programme.
Je lui ai demandé de me donner quelques exemples concrets avant d'aller plus loin.

En ce qui concerne la techno, j'ai finalement opté pour
var valueParts = itemValue.replace(/(@#[A-za-z0-9_-]*)/g, '%%$1%%').split('%%');

c'est à dire (en une seule ligne) ce que j'avais mis comme exemple ce matin.
Mais je n'aurais pas pensé à utiliser un split() si vous ne me l'aviez pas proposé.
Il est sûr que le split avec parenthèses capturantes aurait été plus sexy, mais comme il semble que certains navigateur ne le supportent pas, ma solution bébête me semble préférable. Le tout est qu'il n'y ait pas de "%%" dans le texte, mais comme c'est le cas, ça n'a pas d'impact.
Modifié par PapyJP (31 Mar 2017 - 00:55)