Page 1 sur 1
[R] RegExpReplace sur du CSV
Posté : mar. 14 avr. 2015 16:17
par Clampu
Bonjour

,
Voulant me lancer dans les regexp pour faciliter certains bouts de code, je bute déjà. J'ai une string issue d'un CSV, et je voudrai remplacer un élément de cette string, sans passer par un split sur le ';'.
Voici un exemple du string et de la reg exp que j'utilise :
Code : Tout sélectionner
$data = "02-LOGS;13/04/2015 18:17:59;USA6M1;MMS"
StringRegExp($data, "^[^;]*;[^;]*;([^;]*);[^;]*", 1) ; me renvoie bien ce que je cherche : "USA6M1"
StringRegExpReplace($data, "^[^;]*;[^;]*;([^;]*);[^;]*", "DD") ; je m'attendrai à avoir "02-LOGS;13/04/2015 18:17:59;DD;MMS" mais j'ai "DD"
Ça doit être tout bête, mais je ne trouve pas comment faire pour remplacer uniquement le USA6M1 trouvé et non pas toute la chaine.
Re: [..] RegExpReplace sur du CSV
Posté : mar. 14 avr. 2015 18:54
par jchd
Comme ça ?
Code : Tout sélectionner
Local $data = "02-LOGS;13/04/2015 18:17:59;USA6M1;MMS"
Local $data1 = StringRegExpReplace($data, "(?U)^.*;.*;\K(.*(?=;.*$))", "DD")
ConsoleWrite($data1 & @LF)
Re: [..] RegExpReplace sur du CSV
Posté : ven. 17 avr. 2015 11:32
par Clampu
Yeah super. J'ai dû un peu creuser pour comprendre (notamment le "(?U)" et le "(?=" que je ne connaissait pas, tu peux d'ailleurs m'en dire un peu plus ?), et ça m'a bien aidé.
Pour l'exercice, en respectant ma logique (moins correcte que la tienne), pour faire fonctionner ma regexp :
Code : Tout sélectionner
StringRegExpReplace($data, "^[^;]*;[^;]*;\K([^;]*)(?=;[^;]*)", "DD")
et j'ai pu comprendre pourquoi la mienne était KO. Merci !
Re: [R] RegExpReplace sur du CSV
Posté : ven. 17 avr. 2015 11:34
par jguinch
Re: [R] RegExpReplace sur du CSV
Posté : ven. 17 avr. 2015 16:50
par Clampu
C'est exactement ce que j'avais fait

! sauf que d'après ce
site, j'ai 2 résultats (un en rouge un en vert) ce qui me laissait penser que ce n'était pas possible, je n'ai donc même pas tenté avec autoit

dommage j'aurai perdu moins de temps.
Peux tu m'expliquer pourquoi il remplace le contenu de la seconde parenthèse et pas la première ? Je dois avoir mal compris le principe des parenthèses.
Re: [R] RegExpReplace sur du CSV
Posté : ven. 17 avr. 2015 19:25
par jguinch
Les parenthèses sont des groupes capturants, qui peuvent être réutilisés plus loin dans l'expression et/ou lors d'un remplacement avec StringRegExpReplace (back-reference)
Dans mon exemple, j'ai utilisé deux groupes capturants auxquels je ne fais aucune référence - ni dans l'expression, ni dans le remplacement.
Le premier groupe sert juste à appliquer le {2} à ce groupe. Quant au deuxième, il ne sert strictement à rien (je sais pas pourquoi j'ai mis un groupe là...
Maintenant pour revenir au pourquoi du remplacement, il faut comprendre qu'un remplacement par regex n'opére que sur la partie concernée, parenthèses ou non.
Les parenthèses sont juste des groupes qui servent à matcher une chaîne, rien de plus.
Si je fais StringRegExpReplace("abcde", "abc", "") ou StringRegExpReplace("abcde", "a(b)c", ""), j'ai le même résulat, puisque le remplacement s'effectue sur l'ensemble de l'expression (la partie concernée est abc)
Le \K est justement là pour dire que la partie précédemment matchée n'est pas concernée par le remplacement.
Donc su je fais StringRegExpReplace("abcde", "ab\Kc", ""), seul le "c" sera remplacé, de même avec l'expression StringRegExpReplace("abcde", "a(b)\Kc", "") dans laquelle la capture ne sert à rien.
Si on n'avait pas utilisé le \K, on aurait pu faire un truc du genre StringRegExpReplaceabcde, "(.+)c", "$1") : ici le remplacement opéré sur toute la chaîne "abc".
Le groupe (ab) est capturé dans l'expression et on le réutilise pour le remplacement : ce qui revient à dire :
- j'effectue un remplacement sur :
n'importe quel caractère jusqu'à la lettre "c" (je capture le tout)
suivit de "c"
=> l'expression matche (ab)c
- je remplace (ab)c par $1 ($1 étant le groupe capturé (ab) )
Pour appliquer ça à l'expression d'origine, on aurait pu faire un truc du genre StringRegExpReplace($data, "^((?:[^;]*;){2})[^;]*", "$1DD")
Ici, le remplacement s'effectue sur 02-LOGS;13/04/2015 18:17:59;USA6M1 (seulement la partie qui match l'expression, la partie de droite n'est pas concernée)
On capture donc le groupe (02-LOGS;13/04/2015 18:17:59;) en $1 et on remplace tout (02-LOGS;13/04/2015 18:17:59;)USA6M1 par $1DD
J'espère avoir été suffisamment clair dans ces explications, désolé si si ça t'embrouille...
Re: [R] RegExpReplace sur du CSV
Posté : ven. 17 avr. 2015 20:37
par mikell
Tidiou
C'est pas un message c'est un tutoriel, et très clair en plus (à la 3ème lecture)
Un peu méconnu mais très pratique le \K ("oublie ce qui précède")
Code : Tout sélectionner
Msgbox(0,"", StringRegExpReplace("abcde-abcde-abcde", ".+\Kabc", "X-") )
Code : Tout sélectionner
Local $data = "02-LOGS;13/04/2015 18:17:59;USA6M1;MMS"
Local $data1 = StringRegExpReplace($data, ".+;\K[^;]*(?=;)", "DD")
Msgbox(0,"", $data1)
Re: [R] RegExpReplace sur du CSV
Posté : ven. 17 avr. 2015 20:44
par orax
Sur regex101.com t'as des explications sur l'expression (pour savoir à quoi sert (?U) par exemple).
(?U).*; est pareil que
.*?;
Ta logique n'était pas mauvaise. Et je crois d'ailleurs que l'utilisation de
[^;]* serait meilleure car ça évite des retours sur trace. Il y a les parties
Laziness Instead of Greediness et
An Alternative to Laziness de cette page
http://www.regular-expressions.info/repeat.html qui en parlent. Tu peux aussi utiliser le "regex debugger" de regex101 pour voir le nombre d'étapes qu'il faut pour terminer ; mais ça peut aussi être utile pour comprendre ce qui ne va pas.