11521 sujets

JavaScript, DOM et API Web HTML5

Bonjour à tous

Je cherche à analyser une expression régulière de type nom:valeur, ce qui se fait aisément par
var dataInfo = dataItem.match(/^(.*) : ( .*)$/);
var itemName = dataInfo[1];
var itemValue = dataInfo[2];

Les espaces auour de ":" sont là pour éviter la confusion avec une emoticone Smiley decu
Comme la chaîne contient éventuellement des espaces parasites en début, en fin ou autour du séparateur ":", j'ai essayé de traiter cela en une fois par l'expression
var dataInfo = dataItem.match(/^\s*(.*)\s*:\s*(.*)\s*$/);

Le résultat est que les espaces sont bien supprimés, mais pas à la fin de 'itemValue', ce qui m'oblige à supprimer ces espaces par un replace(/\s*$/, '').
Je comprends très bien pourquoi, mais la question est
"y a-t-il un moyen de fabriquer une expression régulière qui évite de prendre en compte ces espace indésirables?"

Merci de votre aide
Modifié par PapyJP (01 Apr 2016 - 10:26)
Bonjour,
Si nom et valeur ne contiennent pas d'espaces, utilise \S (tout sauf caractère blanc) à la place du sélecteur universel.
Sinon, il faut rendre le quantificateur * (qui devrait être + à mon avis, au moins pour le nom) lazy en y ajoutant un ?
/^\s*(.+?)\s*:\s*(.+?)\s*$/

Bonne continuation.
Bonjour,

Et pourquoi ne pas utiliser les fonctions split() et trim() ? Et au moins tu ne t'embête pas trop avec les regex.
@PapyJP

Si nom et valeur ne contiennent pas d'espaces, ceci devrait marcher (enlever les signes = entourant le : ) :
var dataInfo = dataItem.replace(/ /g,'').match(/(.+)=:=(.+)/);

Modifié par lddsoft (01 Apr 2016 - 16:08)
Merci de vos réponses

Bien entendu, le champ "valeur" (le seul qui pose problème) peut contenir des espaces, c'est pourquoi je n'ai pas utilisé ces expression.
Pour l'instant, j'ai effectivement "trimmé" la chaîne de caractères, mais je me demandais q'il n'y avait pas plus astucieux.
Probablement non.
@PapyJP

Peut-être un peu lourd, mais ceci semble répondre à votre souhait :
var dataInfo = dataItem.replace(/^\s*/,'').replace(/\s*:\s*/,':').replace(/\s*$/,'').split(':');
En fait, ce qui n'allait pas dans la regex, c'est (.*)\s*, car le(s) espaces étai(en)t englobé(s) dans les couples de parenthèses (.*), le point signifiant "n'importe quel caractère (donc espace compris)". Smiley cligne

EDIT:
var dataInfo = dataItem.trim().replace(/\s*:\s*/,':').split(':');

Modifié par lddsoft (02 Apr 2016 - 20:17)
@lddsoft

Merci de ta réponse. C'est à peut près ce que j'ai fait... et que j'essayais d'éviter de faire.

Je me demandais simplement s'il n'y avait pas une solution plus élégante que je ne voyais pas, il semble bien que non.
Quand on est retraité, on peut pas échanger avec son voisin de bureau, le forum est un excellent moyen (en fait le seul) d'améliorer ses connaissances et sa pratique.
Bonjour,
Avez-vous lu l'intégralité de mon message ? La seconde réponse que j'y donnais, c'est à dire ajouter un point d'interrogation au quantificateur, fait justement que (.*) ne capture plus les espaces.

Explication : En tant normal, un sélecteur capture le plus de caractères possible (il est greedy). Si un sélecteur suivant vient à échouer dans sa sélection de caractères, le moteur fait ce qu'on appelle du backtracking (machine arrière) : le premier sélecteur abandonne un caractère et on repart pour un tour. L'opération se répète jusqu'à ce que le premier sélecteur échoue, faisant échouer l'expression entière, ou que l'expression réussisse.

Dans notre exemple, .* sélectionne et capture également les espaces, \s* ne sélectionne rien avec succès comme l'y autorise son quantificateur, et la chaîne valide bien l'expression.

En rendant le quantificateur lazy (ajout du "?"), la sélection est minimale : (.*?) commence par ne rien sélectionner, idem pour \s* mais le nom (disons qu'il ne contient que des lettres) n'est pas sélectionné par le ":". Le moteur fait alors du backtracking et comme \s* va échouer dans sa sélection d'un caractère blanc, c'est (.*?) qui essaie de sélectionner un caractère de plus, et ceci jusqu'à la fin du "nom", puisqu'à ce moment-là \s* pourra sélectionner les espaces jusqu'au caractère ":" (ou jusqu'à la fin de la chaîne pour la sélection de "valeur").

C'est assez bien expliqué ici, en anglais
++
Modifié par Seven tears (03 Apr 2016 - 17:22)
Merci Seven tears, effectivement je n’avais pas compris ce que tu voulais dire.
Je me disais bien qu'il devait y avoir un moyen de faire ça.
Je vais tester ça, ça semble LA bonne solution.

Edit: après test, c'est tout à fait ce que je cherchais
Modifié par PapyJP (03 Apr 2016 - 19:09)
Re,
Le quantificateur lazy est en effet une bonne solution (dans le sens où elle répond parfaitement au problème) mais peut-être pas la plus performante. La solution de SolidSnake semble plus appropriée de ce point de vue, même si elle nécessite une ou deux instructions de plus. Je n'ai fait que proposer une solution d'après la première piste envisagée (regex).
Modifié par Seven tears (04 Apr 2016 - 00:19)
Sûr que ça ne doit pas être extrêmement performant quand on voit comment c'est fait (très bien expliqué dans le lien en anglais que tu as donné). Donc à utiliser avec modération, pas dans une boucle qui tourne à tout bout de champ. Mais c'est plutôt pour améliorer ma culture dans le domaine que j'ai posé cette question.
Les expressions régulières sont un domaine que j'ai très peu pratiqué depuis près de 20 ans que je fais du JS. Il se trouve maintenant que j'en ai besoin, il n'est pas trop tard pour s'y mettre Smiley smile