RegExp récupérer Submatches ?

Résolu
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020
- 13 déc. 2017 à 21:39
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
- 18 déc. 2017 à 13:44
Bonjour,
Je bute sur la récupération des Submatches des (groups) de mon pattern.
J’espère que ce que j’essaie de faire est réalisable?
Pouvez-vous m’aider?

TxtSource = "\\\*-****/Un test, Pourquoi faire? c'est fou ça! \****-*///"
ReslutSpeciChars = ""

Dim strText, RegularExpressioN

'([^\,]|^)([\,])(?![\,])
'[^\,] = n'est pas une virgule.
'| = ou.
'^ = est au début de la chaîne.
'(?![\,]) = n'est pas suivit d'une virgule.
'Equivalent a (?<![\,])[\,](?![\,]) soit (pas de virgule avant, pas de virgule après), mais non supporter par vb (test arrière (?<!....).

'"\" =([^\\]|^)([\\])(?![\\])
'"/" =([^\/]|^)([\/])(?![\/])
'"*" =([^\*]|^)([\*])(?![\*])

FindSpeciChars = "([^\\]|^)([\\])(?![\\])"_
& "|([^\/]|^)([\/])(?![\/])"_
& "|([^\*]|^)([\*])(?![\*])"

strText = TxtSource
Set RegularExpressioN = New RegExp
RegularExpressioN.Pattern = FindSpeciChars
RegularExpressioN.Global = True
Set Matches = RegularExpressioN.Execute(strText)
If Matches.Count > 0 Then
MatchMsg = Matches.Count & " correspondance(s) trouvée(s)." & vbCRLF
For Each Match In Matches
MatchMsg = MatchMsg & "Correspondance trouvée """ & match.Submatches(1) & """ en position: " & match.FirstIndex + Len(match.SubMatches(0)) & vbCrLf
Next
'MsgBox MatchMsg
Else
MsgBox "Aucun match", 0, "VBScript RegExp Tester"
End If
strText = RegularExpressioN.Replace(strText, "$&")'"$1" "$&"
Set RegularExpressioN = Nothing
ReslutSpeciChars = strText

MsgBox TxtSource & vbCrLf & ReslutSpeciChars & vbCrLf & MatchMsg

12 réponses

jordane45
Messages postés
35405
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
16 mai 2022
356
13 déc. 2017 à 22:40
Bonjour,
Ton pattern ne semble pas bon.
Commence par le tester en ligne, par exemple ici : http://regexstorm.net/tester
Sinon.. décris nous exactement ce que tu espères obtenir.

0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

13 déc. 2017 à 23:33
Bonjour,
Mon pattern est bon :

([^\\]|^)([\\])(?![\\])|([^\/]|^)([\/])(?![\/])|([^\*]|^)([\*])(?![\*])

Prenons l’exemple avec le caractère ",".
Normalement j’aurais du utiliser ce pattern : (?<![\,])[\,](?![\,]) soit (pas de virgule avant, pas de virgule après).
Vu que le langage VBScript ne supporte pas les tests arrière (?<!…), il a fallu ruser, en décrivant et en consommant la position avant le caractère ciblé: ([^\,]|^)([\,])(?![\,]) (cette position peut être soit le début de la chaîne ^, soit un caractère qui n'est pas une virgule [^\,]). Ce qui change, c'est que deux caractères sont consommés par la pattern (le caractère précédent et le caractère cible).
Pour le remplacement, il est nécessaire de mettre une référence au groupe de capture dans la chaîne de remplacement pour restituer le caractère qui précède le caractère cible.
Le code fonctionne bien avec mon première caractère "\" soit le pattern: ([^\\]|^)([\\])(?![\\]) mais des que je veux traiter les deux autres !!!(groupes séparés par "|").

Je bute sur la manière d’adapter mes matches pour le value et la position de mes caractères.
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

Modifié le 14 déc. 2017 à 00:11
Voici le test qui fonctionne :

Référence au groupe de capture "$1".

"$&" est sensé reprendre tous les groupes de capture pour la suite.

TxtSource = "\\\*-****/Un test, Pourquoi faire? c'est fou ça! \****-*///"
ReslutSpeciChars = ""

Dim strText, RegularExpressioN

'([^\,]|^)([\,])(?![\,])
'[^\,] = n'est pas une virgule.
'| = ou.
'^ = est au début de la chaîne.
'(?![\,]) = n'est pas suivit d'une virgule.
'Equivalent a (?<![\,])[\,](?![\,]) soit (pas de virgule avant, pas de virgule après), mais non supporter par vb (test arrière (?<!....).

'"\" =([^\\]|^)([\\])(?![\\])
'"/" =([^\/]|^)([\/])(?![\/])
'"*" =([^\*]|^)([\*])(?![\*])

FindSpeciChars = "([^\\]|^)([\\])(?![\\])"

strText = TxtSource
Set RegularExpressioN = New RegExp
RegularExpressioN.Pattern = FindSpeciChars
RegularExpressioN.Global = True
Set Matches = RegularExpressioN.Execute(strText)
If Matches.Count > 0 Then
MatchMsg = Matches.Count & " correspondance(s) trouvée(s)." & vbCRLF
For Each Match In Matches
MatchMsg = MatchMsg & "Correspondance trouvée """ & match.Submatches(1) & """ en position: " & match.FirstIndex + Len(match.SubMatches(0)) & vbCrLf
Next
'MsgBox MatchMsg
Else
MsgBox "Aucun match", 0, "VBScript RegExp Tester"
End If
strText = RegularExpressioN.Replace(strText, "$&")
Set RegularExpressioN = Nothing
ReslutSpeciChars = strText

MsgBox TxtSource & vbCrLf & ReslutSpeciChars & vbCrLf & MatchMsg
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
14 déc. 2017 à 00:01
Bonsoir,

Peux tu mettre le resultat que tu attends à partir du texte que tu as mis en exemple?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

14 déc. 2017 à 00:03
Le bute est de récupérer les caractères isolés .
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
14 déc. 2017 à 00:14
C’est pas clair, j’ai mis ton code « qui marche » dans regexstorm, et ça capture un anti slash coincé entre un espace et une étoile. C’est pas ce que j’appellerais isolé.
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

Modifié le 14 déc. 2017 à 00:40
Attention j'ai corrigé mon exemple qui fonctionne sûrement entre temps. ds le replace j'ai remplacé "$1" par "$&"
Quand je dis isolé c'est isolé d'un groupe de caractères identiques.
Le résultat du MsgBox est :
1 correspondance(s) trouvé(s).
Correspondance trouvée "\" en position: 49
Ce qui est exacte.
As tu vu l'explication poste 2?
match.Submatches(1) me supprime l’espace avant le caractère et me le retourne.
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
14 déc. 2017 à 07:14
Avant de supprimer et de remplacer,n je voudrais comprendre ce que tu cherches à capturer.
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

14 déc. 2017 à 09:57
Dans l'exemple du poste n°3 je recherche la ou les occurrences "\" qui ne font pas partie d'un groupe "\\\".
Pour le pattern utilisé voir explication du poste n°2.
Explication supplémentaire:
Caractères spéciaux
(\#) Correspond au caractère (#) suivant le backslash (exceptés les caractères a-z et 0-9).
Par exemple, la séquence "\\" signifie "\" , "\." correspond au caractère "." (stop), "\$" correspond à "$".
0
jordane45
Messages postés
35405
Date d'inscription
mercredi 22 octobre 2003
Statut
Modérateur
Dernière intervention
16 mai 2022
356 > NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

14 déc. 2017 à 10:32
Bonjour,
Whismeril ne te demande pas de lui expliquer comment fonctionne une regex ni ce que sont les pattern que tu utilises...
Il veut (et il n'est pas le seul...) savoir ce que tu souhaites EXACTEMENT obtenir en partant de ta phrase d'exemple de ton premier message......

En gros...
TxtSource = "\\\*-****/Un test, Pourquoi faire? c'est fou ça! \****-*///"

Resultat attendu : .................................... (remplir ici ! )

Merci.
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596 > NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

14 déc. 2017 à 12:06
Comme le dit Jordane, je sais me servir des regex, c’est même un jeu que j’apprécie. Cependant dans ton cas, je n’arrive pas à faire le lien entre ce que tu expliques et les patterns que tu montres.
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

14 déc. 2017 à 12:13
Le résultat du remplacement attendu n'est pas visible vu que je remplace le caractère par lui-même.
J'ai besoin de ce remplacement pour la suite de mon programme.

Pour voir ce qui est trouvé ajouter des parenthèses autour du $& soit ($&) ce qui donne au replace pour les caractères "\","/" et "*".

TxtSource = \\(\*)-***(*/)Un test, Pourquoi faire? c'est fou ça!( \)****(-*)///
Jusque-là pas de problème le remplacement est bon.

C'est au niveau de la récupération de la valeur et de la position de de mes caractères que ça coince
En utilisant le pattern: ([^\\]|^)([\\])(?![\\]) pour le caractères "\" c'est bon le résultat du MsgBox est:
1 correspondance(s) trouvé(s).
Correspondance trouvée "\" en position: 49

Mais, dès que j'essaie un pattern avec les caractères "\"|"/"|"*".
([^\\]|^)([\\])(?![\\])|([^\/]|^)([\/])(?![\/])|([^\*]|^)([\*])(?![\*])

Le résultat est :
4 correspondance(s) trouvé(s).
Correspondance trouvée "" en position: 2
Correspondance trouvée "" en position: 8
Correspondance trouvée "\" en position: 49
Correspondance trouvée "" en position:54

J'aimerais avoir ceci:
4 correspondance(s) trouvé(s).
Correspondance trouvée "*" en position: 3
Correspondance trouvée "/" en position: 9
Correspondance trouvée "\" en position: 49
Correspondance trouvée "*" en position:55
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
14 déc. 2017 à 12:36
4 correspondance(s) trouvé(s).
Correspondance trouvée "*" en position: 3
Correspondance trouvée "/" en position: 9
Correspondance trouvée "\" en position: 49
Correspondance trouvée "*" en position:55
Voilà c’est tout ce qui m’intéresse. Je tache d’y regarder cet après-midi
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

14 déc. 2017 à 12:55
Désolé je n'avais pas compris t'as demande ! Sympa de te pencher sur mon problème.
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
14 déc. 2017 à 14:02
VBS accepte les groupes avec des noms?
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
14 déc. 2017 à 14:21
En pariant que oui, regarde ce lien (non cliquable à cause d'un vieux bug du site)

http://regexstorm.net/tester?p=%28%28%3f%3cavant%3e%5b%5e%5c%5c%5d%29%28%3f%3ctoto%3e%5c%5c%29%28%3f%3capres%3e%5b%5e%5c%5c%5d%29%29%7c%28%28%3f%3cavant%3e%5b%5e%5c*%5d%29%28%3f%3ctoto%3e%5c*%29%28%3f%3capres%3e%5b%5e%5c*%5d%29%29%7c%28%28%3f%3cavant%3e%5b%5e%2f%5d%29%28%3f%3ctoto%3e%2f%29%28%3f%3capres%3e%5b%5e%2f%5d%29%29&i=%5c%5c%5c*-****%2fUn+test%2c+Pourquoi+faire%3f+c%27est+fou+%c3%a7a!+%5c****-*%2f%2f%2f&r=%24%7bavant%7d%7c%24%7bapres%7d
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

14 déc. 2017 à 15:38
(?<avant>[^\\])(?<toto>\\)(?<apres>[^\\]))|((?<avant>[^\*])(?<toto>\*)(?<apres>[^\*]))|((?<avant>[^/])(?<toto>/)(?<apres>[^/]))


Error: Erreur de syntaxe dans l'expression régulière
Code: 800A1399
Source: Erreur d'exècution Microsoft VBScript
System: La ressource de cluster n'a pas pu êtrz créée dans le moniteur de resources spécifié.

Toujours ce problème de test arrière avec VBS?
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

Modifié le 14 déc. 2017 à 22:33
Sous vbs le résultat est identique au donnée de l’onglet Context de regexstorm:
\\\|-****|Un test, Pourquoi faire? c'est fou ça! |****-|///

Hâte de voir comment tu va traiter la suite, encore merci !
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
14 déc. 2017 à 22:35
Quelle suite?
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

Modifié le 14 déc. 2017 à 23:16
J'aimerais avoir ceci:
4 correspondance(s) trouvé(s).
Correspondance trouvée "*" en position: 3
Correspondance trouvée "/" en position: 9
Correspondance trouvée "\" en position: 49
Correspondance trouvée "*" en position:55

poste N°13

Au final sur le remplacement, ton pattern fait la même chose que le mien sauf que si la chaîne commence par un des caractères défini est qu’il ne fait pas partie d’un groupe de caractères identique, ça ne fonctionne pas et il ne reprend pas le caractère d’origine.

j’en reviens a l’idée de départ, qui me fait penser que mon problème n’est pas un problème de pattern, mais bien un problème de traitement sous vbs !
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
15 déc. 2017 à 07:34
4 correspondance(s) trouvé(s).
Correspondance trouvée "*" en position: 3
Correspondance trouvée "/" en position: 9
Correspondance trouvée "\" en position: 49
Correspondance trouvée "*" en position:55


ça c’est en VBS que tu dois l’fficher. Et je ne connais pas VBS.
Par contre, comme tu peux le voir sur regexstorm, la capture n’est pas toujours au même index, il faut donc dans ta boucle foreach tester quelle est la capture valide et afficher les données associées.

Au final sur le remplacement, ton pattern fait la même chose que le mien sauf que si la chaîne commence par un des caractères défini est qu’il ne fait pas partie d’un groupe de caractères identique, ça ne fonctionne pas et il ne reprend pas le caractère d’origine.

Peux donner un morceau de texte qui ne marche pas?
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

Modifié le 15 déc. 2017 à 09:38
Pour l'exemple j'ai ajouté "\-" devant le texte.
\-\\\*-****/Un test, Pourquoi faire? c'est fou ça! \****-*///
Mon souci est, je pense aussi au niveau de la manière de récupérer les infos des groupes de capture.
"La boucle For Each" je ne sais pas trop comment la gérer.
C'est pour cela que j'ai posté sur le forum VBScript et non sur RegExp.
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
15 déc. 2017 à 10:33
Alors pour le \- c’est bien un problème de pattern, je n’ai pas géré le debut de texte (ni la fin d’ailleurs).
Et donc avant de regler le soucis de boucle réglons, les regex.
Est ce que tu veux capturer le - aussi?
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

15 déc. 2017 à 17:00
Voici la solution retenue en grand merci Whismeril

Sub Macro1()

Dim pattern As String
Dim texte As String
pattern = "([^\\]|^)([\\])(?![\\])|([^\/]|^)([\/])(?![\/])|([^\*]|^)([\*])(?![\*])|([^\-]|^)([\-])(?![\-])"
texte = "\-\\\*-****/Un test, Pourquoi faire? c'est fou ça! \****-*///*/"

Dim regex As VBScript_RegExp_55.RegExp
Set regex = New VBScript_RegExp_55.RegExp
regex.pattern = pattern
regex.Global = True

Dim match As VBScript_RegExp_55.match
Dim matches As VBScript_RegExp_55.MatchCollection
Set matches = regex.Execute(texte)
Debug.Print matches.Count

Dim sortie As String
For Each match In matches
For i = 1 To match.SubMatches.Count - 1 Step 2
If Not (match.SubMatches(i) = "") Then
Debug.Print ("Correspondance trouvée """ & match.Submatches(i) & """ en position: " & match.FirstIndex + Len(match.Value) - 1)
End If
Next i
Next match

End Sub


Je rencontre un nouveau problème!
Si deux caractères "seule" et côte à côte seule le 1er et prit en compte
/**** *\\/ Ok pour le 0 le 6 et le 9
/**** *\ Ok pour le 0 et le 6 mais pas le 7
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
15 déc. 2017 à 18:18
Là, je ne suis pas sûr, mais il me semble que c'est une limitation des regex: 2 captures ne se chevauchent pas.
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
15 déc. 2017 à 18:23
Là ça marche
http://regexstorm.net/tester?p=%28%5b%5c%5c%5c*%2f-%5d%29%28%3f%3c!%5c1%5c1%29%28%3f!%5c1%29&i=%5c-%5c%5c%5c*-****%2fUn+test%2c+Pourquoi+faire%3f+c%27est+fou+%c3%a7a!+%5c****-*%2f%2f%2f*%2f&r=%7c

Mais ce pattern est refusé par VBS.

T'es obligé de faire du VBS, VB.Net accepte ce pattern
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

Modifié le 15 déc. 2017 à 23:53
Je dois dans la mesure du possible rester sous VBScript. Penses tu qu’il soit possible de traiter chaque "sous patterns" indépendamment ?
Dans une sorte de boucle et surtout récupérer chaque positions et valeurs?
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
16 déc. 2017 à 00:03
Oui
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

16 déc. 2017 à 14:13
N’étant pas très a mon aise, avec la gestion d’une boucle dans ce contexte de multiple sous pattern,
j’appréciais beaucoup qu’une personne expérimentée puisse me donner un exemple complet.
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
16 déc. 2017 à 21:32
Ceci marche sous VBA
Sub Macro1()
 Dim texte As String
 texte = "\-\\\*-****/Un test, Pourquoi faire? c'est fou ça! \****-*///*/"

 For Each Caractere In Array("\\", "\*", "-")
      Recherche Caractere, texte
 Next
End Sub


Sub Recherche(ByVal Caractere As String, texte As String)
 Dim Pattern As String
 Pattern = "([^" & Caractere & "]|^)(" & Caractere & ")(?!" & Caractere & ")" 'on fait un pattern

 Dim regex As VBScript_RegExp_55.RegExp
 Set regex = New VBScript_RegExp_55.RegExp
 regex.Pattern = Pattern
 regex.Global = True

 Dim match As VBScript_RegExp_55.match
 Dim matches As VBScript_RegExp_55.MatchCollection
 Set matches = regex.Execute(texte)
 Debug.Print "Le pattern " & Pattern & " retourne " & matches.Count; " captures"

 Dim sortie As String
 For Each match In matches
        For i = 1 To match.Submatches.Count - 1 Step 2
            If Not (match.Submatches(i) = "") Then
                Debug.Print ("Correspondance trouvée """ & match.Submatches(i) & """ en position: " & match.FirstIndex + Len(match.Value))
            End If
        Next i
 Next match

End Sub
0
NeriXs
Messages postés
116
Date d'inscription
lundi 4 mai 2015
Statut
Membre
Dernière intervention
18 août 2020

18 déc. 2017 à 13:31
Bonjour,
C'est impeccable! Merci
Juste une petite erreur.
Les caractères sont décalés de + 1.
Modification de la ligne 30
Debug.Print ("Correspondance trouvée """ & match.Submatches(i) & """ en position: " & match.FirstIndex + Len(match.Value) - 1)
0
Whismeril
Messages postés
17326
Date d'inscription
mardi 11 mars 2003
Statut
Modérateur
Dernière intervention
15 mai 2022
596
18 déc. 2017 à 13:44
Pense à marquer le sujet résolu, si ça te convient
0