Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3029 connectés 

  FORUM HardWare.fr
  Programmation
  Javascript/Node.js

  Regex : capturer toutes les itérations d'un groupe capturant +

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Regex : capturer toutes les itérations d'un groupe capturant +

n°2311235
naeco
Buddy Rich Big Band
Posté le 18-02-2018 à 12:11:16  profilanswer
 

Bonjour,
Je n'arrive pas à finaliser mon expression régulière, peut-être qu'il y aura un expert parmi vous qui saura m'aider  :sol: Voici formellement l'énoncé :
 

  • j'ai un string qui contient quelque chose de la forme : puissance=48MW/h
  • Je veux récupérer le libellé, le signe de comparaison, le nombre et tout le détail des unités, soit ici :
  • puissance, = , 48, M, W, / et enfin h
  • La première partie, aucun problème donc nous allons nous focaliser uniquement sur l'unité.
  • Pour simplifier, nous allons dire qu'il y a que 2 multiples c et m, qu'il y a que 4 unités possibles W, h, Z et y
  • Et pour bien visualiser quel groupe capture quoi, on va dire que les unités pouvant avant le slash seront W et h, être après le slash sont Z et y
  • Je ne double volontairement pas les slashs qui devraient l'être pour pouvoir tester facilement les expressions rationnelles dans https://regex101.com/


La première expression rationnelle qui vient est :  

Code :
  1. var regex = new RegExp("(c|m)?(h|W)+(?:([\/]?)(Z|y)+)?","ug" );


Testons là sur :

Code :
  1. mWh/Zy


 
Le problème est que comme le fait remarquer l'analyseur de RegEx https://regex101.com/:

Citation :


A repeated capturing group will only capture the last iteration. Put a capturing group around the repeated group to capture all iterations or use a non-capturing group instead if you're not interested in the data


 
Donc ce qu'il revient est très logiquement :
 

Code :
  1. Match 1
  2. Full match 0-6 `mWh/Zy`
  3. Group 1. n/a `m`
  4. Group 2. n/a `h`
  5. Group 3. n/a `/`
  6. Group 4. n/a `y`


 
Si j'applique la solution proposée par l'analyseur l'expression régulière devient :
 

Code :
  1. var regex = new RegExp("(c|m)?((?:h|W)+)(?:([\/]?)((?:Z|y)+))?","ug" );


 
et on obtient une fois appliqué sur le même string :
 

Code :
  1. Full match 0-6 `mWh/Zy`
  2. Group 1. n/a `m`
  3. Group 2. n/a `Wh`
  4. Group 3. n/a `/`
  5. Group 4. n/a `Zy`


 
Mais ce n'est toujours pas ce que je veux  :cry: , moi je veux  
 

Code :
  1. Full match 0-6 `mWh/Zy`
  2. Group 1. n/a `m`
  3. Group 2. n/a `W`
  4. Group 3. n/a `h`
  5. Group 4. n/a `/`
  6. Group 5. n/a `Z`
  7. Group 6. n/a `y`


 
Quelqu'un aurait une idée ?
 
Merci !  :bounce:
 
Edit : je me penche vers une analyse en plusieurs fois bouclant sur une application de RegExp.prototype.exec() (voir en bas de https://developer.mozilla.org/fr/do [...] egExp/exec), mais ça ne me satisfait pas des tonnes...


Message édité par naeco le 18-02-2018 à 12:16:03
mood
Publicité
Posté le 18-02-2018 à 12:11:16  profilanswer
 

n°2311236
MaybeEijOr​Not
but someone at least
Posté le 18-02-2018 à 15:31:07  profilanswer
 

Bonjour,
 
Pas tout compris à ton exemple simplifié alors je me suis permis d'en refaire un :
- première unité : "a" ou "b"
- multiplicateur de la première unité : "M" ou "k" ou aucun
- seconde unité : "x" ou "y"
- multiplicateur de la seconde unité : "m" ou "µ" ou aucun
 
Expression de la forme : [nom du résultat][signe de comparaison][nombre][multiplicateur de première unité optionnel][première unité][opérateur d'unité composée][multiplicateur de seconde unité optionnel][seconde unité]
 

Code :
  1. var str = "puissance=48Ma/x";
  2. var regex = /(\w+)(.)(\d+)(M|k)?(a|b)(.)?(m|µ)?(x|y)/;
  3. var result = regex.exec(str);
  4. console.log(result);


 
Mais j'ai du mal à comprendre ce que tu attends au niveau du signe de comparaison et de l'opérateur d'unité composée.
Tu auras vraiment autre chose que des "=" pour le signe de comparaison ? Genre des ">" ou même des ">=" ?
Pareil, pour l'unité tu attends toujours une unité composée ? Peux-tu avoir des unités composées avec des opérateurs implicites (i.e. "MWh" ) ?


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2311238
naeco
Buddy Rich Big Band
Posté le 18-02-2018 à 17:08:51  profilanswer
 

Merci de ta réponse.
 
Oui tu as compris, juste un petit truc, dans une unité, il ne peut y avoir qu'un seul multiple, genre des newton-mètres peuvent être en mNm (mili Newton mètre, mais pas en mNmm (mill Newton milimètre)
 
Et oui, l'idée est de couvrir n'importe quelle combinaison d'unitée. Par exemple 1 J = 1 kg.m2.s-2 .
 
Donc il faut mettre un + après ton a|b et x|y, et là, c'est le drame car comme le dit la doc "A repeated capturing group will only capture the last iteration."...
 
Au final, j'ai avancé en le faisant en plusieurs fois : une fois l'unité isolée, je la sépare en deux s'il y a un signe divisé ou pas, et je traite les une ou deux parties ensuite.... C'est moins élégant que d'avoir réussi à faire une méga regex qui fait tout d'un coup, mais au final, ça fera du code peut être plus simple à relire...
 
Mais pour la démarche, la question est toujours d'actualité. Indépendamment du sujet, la question est :
 
Comment capturer toutes les itérations d'un groupe capturant "+"?


Message édité par naeco le 18-02-2018 à 17:09:17
n°2311239
h3bus
Troll Inside
Posté le 18-02-2018 à 17:32:45  profilanswer
 

J'aurai utilisé un groupe npon capturant

Code :
  1. (\w+)([\>\<\=]+)([\d\.\,]+)((?:[pnµmkM]?[gmNsWh](?:-?\d+)?[\.\/]?)+)
 

En plus de détails:
- Capture de l'identifiant + comparaison + nombre (avec virgule ou point): (\w+)([\>\<\=]+)([\d\.\,]+)
- Capture de l'unité avec un groupe non capturant incluant les unités atomiques ((?:<unité atomique> )+)
- Ensuite définition d'une unité atomique: [pnµmkM]?[gmNsWh](?:-?\d+)?
- Et le séparateur d'unité éventuel: [\.\/]?

 

Cette regexp laissera passer plein de truc invalide, mais en supposant que ta chaine ne comporte pas nimp.


Message édité par h3bus le 18-02-2018 à 17:38:15

---------------
sheep++
n°2311242
MaybeEijOr​Not
but someone at least
Posté le 18-02-2018 à 19:07:50  profilanswer
 

Le problème reste le même, comme dit, on ne peut pas capturer un nombre indéfini de motifs, c'est soit 0 soit 1 mais pas plus.
 
De toute façon je pense si c'était possible tu partirais sur une variable illisible. Je serai parti sur une capture des principaux éléments pour ensuite retravailler sur l'unité entière qui aura été capturée :

Code :
  1. function parse_datas(str) {
  2.   var regex1 = /(\w+)(.)(\d+)(.+)/;
  3.   var result = regex1.exec(str);
  4.   var resultat_regexp = {
  5.      'nom': result[1],
  6.      'comparateur': result[2],
  7.      'valeur': result[3],
  8.      'unite': result[4],
  9.   };
  10.   console.log(resultat_regexp);
  11.   var unite = result[4].split(/(\*|\.|\/)/);
  12.   console.log(unite);
  13.   var regex2 = /([a-zA-Z])?([a-zA-Z])\^?(-|\+)?(\d+)?/;
  14.   var sous_unites_brut = unite.map(val => regex2.exec(val)||val);
  15.   console.log(sous_unites_brut);
  16.   var sous_unites_corr = [];
  17.   sous_unites_brut.forEach(function(el,i){
  18.      if (Array.isArray(el)) {
  19.         sous_unites_corr[i] = {
  20.            'multiplicateur': el[1] === undefined? "":el[1],
  21.            'unite': el[2] === undefined? "":el[2],
  22.            'signe_exposant': el[3] === undefined? "":el[3],
  23.            'exposant': el[4] === undefined? "":el[4]
  24.         };
  25.      } else {
  26.         sous_unites_corr[i] = el;
  27.      }
  28.   });
  29.   console.log(sous_unites_corr);
  30.   console.log('Le multiplicateur de la première sous-unité (le "' + sous_unites_corr[0].unite + '" ) est "' + sous_unites_corr[0].multiplicateur + '", la troisième sous-unité (la "' + sous_unites_corr[4].unite + '" ) est élevée à la puissance "' + sous_unites_corr[4].signe_exposant + sous_unites_corr[4].exposant + '" alors que la seconde sous-unité (le "' + sous_unites_corr[2].unite + '" ) est élevé à la puissance "' + sous_unites_corr[2].signe_exposant + sous_unites_corr[2].exposant + '" mais a pour multiplicateur "' + sous_unites_corr[2].multiplicateur + '".');
  31. }
  32. parse_datas('puissance=48kg.mm2.s-2');


 
Normalement comme ça tu gardes les infos nécessaires à une éventuelle conversion et peux y accéder facilement.
 
EDIT : version plus propre...


Message édité par MaybeEijOrNot le 19-02-2018 à 11:33:35

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Javascript/Node.js

  Regex : capturer toutes les itérations d'un groupe capturant +

 

Sujets relatifs
filtre avec REGEX[RESOLU] LDAP groupe
Regex Split tableau[PHP] pourquoi ma regex ne marche pas ?
[Regex] prenant en compte le caractère "à"Groupe programmation Java
[VBS] Script d'intégration dans un groupe de sécurité[Perl] simplifier ma regex
Url Rewriting - RegexAutomatiser détection faciale et numérotation d’une photo de groupe
Plus de sujets relatifs à : Regex : capturer toutes les itérations d'un groupe capturant +


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR