Question
Regex pour newbie
- Gabriel
-
Auteur du sujet
- Hors Ligne
- Membre elite
-
- Messages : 248
- Remerciements reçus 1
Je cherche un petit coup de main pour utiliser correctement un regex.
Le besoin:
a. Recuperer le nom d'un formulaire qui se trouve dans un fichier XML mal formaté. On ne peut pas utiliser l'import XML (j'ai essayé , il y a des caracteres que l'import XML ne comprend pas. Et on ne doit pas modifier le fichier)
b. il me faut donc parser le fichier, trouver la bonne ligne, puis dans cette ligne extrainre la bonne valeur. Sortir une log avec le vrai nom du fichier et le nom du rapport en face.
c. les données (petit exemple de données a parser):
[code:1]<LocalContainerPreFilter Apply=\"true\" Description=\"Recurse All Levels\" ClassID=\"{A3742FB8-E657-3BF9-B681-92D23A5A2467}\" RecursionLevel=\"536870912\"/>
</ScopeItem>
</ScopeItems><GlobalPreFilters/>
</ObjectScope>
<Reports><Report FilterString=\"\" ReportCreator=\"\" FilterObject=\"\" ReportOptions=\"\" CollectionMethod=\"0\" DateRange=\"0\" Mode=\"0\" ChangeHistoryFromLow=\"766449792\" ChangeHistoryFromHigh=\"29985673\" ChangeHistoryToLow=\"766449792\" ChangeHistoryToHigh=\"29985673\" Screen=\"0\" StandardLayout=\"1\" PortraitLayout=\"1\" AppendDateStamp=\"0\" OneFilePerPage=\"0\" File=\"1\" FileType=\"4\" AllowFieldChanges=\"true\" AllowGrouping=\"true\" AllowTrackChanges=\"true\" FilteringAllowed=\"false\" ObjectClassID=\"-1\" Range=\"0\" RangeType=\"0\"><ReportInformation ID=\"{00000000-0000-0000-0000-000000000149}\" Name=\"EQD Domain Summary\" Category=\"4\"/>
</Report>
</Reports>[/code:1]
d. la données a recuperer dans l'exemple est Name=\"EQD Domain Summary\"
e. la regex que j'ai trouvé [code:1](?<=Name=\"«»)([^\"]+)[/code:1]
elle me donne exactement le champs mais il faut seulement l'executer dans la ligne qui commence \"Report FilterString\" (car le champ name= apparait plusieurs fois et seul celui de cette ligne m'interesse).
f. ce que j'essaie de taper pour simplement recuperer le champs (et qui marche pas)
[code:1]$Chemin = c:\temp
$RegExA = (?<=Name=\"«»)([^\"]+)
gci $Chemin -recurse -filter *.inf | foreach { [regex]::match($_,'$RegExA).value }[/code:1]
l'idee de la commande est de simplement pour chaque fichier m'afficher dans la console la valeur qui m'interesse. j'ai regarder a droite a gauche et a force de modifier ce bout de code je sais meme plus si ca vient de ma regex ou de mon Foreach (je soupgonne quand meme beaucoup mon foreach que j'ai tripoter dans tous les sens...
Si l'un de vous peu m'eclairer...
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
Je ne comprends pas la première partie, tu peux m'expliquer ?e. la regex que j'ai trouvé [code:1](?<=Name=\"«»)([^\"]+)[/code:1]
tonic8 écrit:
Après pas mal d'essaiselle me donne exactement le champs mais il faut seulement l'executer dans la ligne qui commence \"Report FilterString\" (car le champ name= apparait plusieurs fois et seul celui de cette ligne m'interesse).
[code:1]
$r='<Report FilterString=.*[^>]><ReportInformation.*[^>] Name=\"(.*[^>])\".*[^>]=.*/>'
gc test.inf | Where { $_ -match $r }|% {$matches}
[/code:1]
sur les lignes précisées plus celles-ci:
Je ne pense pas que ce soit la meilleure solution mais elle semble répondre au besoin.<Reports><Report FilterString=\"\" ><ReportInformation /><Report FilterString=\"\"><ReportInformation Name=\"V5 EQD Domain Summary\" Test=\"r\"/>
<Reports><Report FilterString=\"\" ><ReportInformation /><Report FilterString=\"\"><ReportInformation FullName=\"V6 ne doit pas matché\" Test=\"r\"/>
<Tests><Test FilterString=\"\" ><TestReportInformation /><Test Name=\"V7 ne doit pas matché\" />
Pour le moment elle ne fonctionne QUE SI chaque ligne du fichier xml ne contient qu'un élément \"Report...\".
Pour ce type d'exercice il faut connaitre les diverses construction possible du fichier. Dans ton cas j'ai un doute, mais toi seul peut le savoir. C'est à dire, si le fichier xml est mal formaté il faut être sûr qu'il le soit tjr de la même manière ( cohérent dans l'erreur en quelque sorte
Et sinon tu n'as pas la possibilité de demander une correction auprès de l'émetteur de ce fichier, plutot que t'adapter au problème ?
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Gabriel
-
Auteur du sujet
- Hors Ligne
- Membre elite
-
- Messages : 248
- Remerciements reçus 1
Alors le mauvais formatage est qu'un certain nombre de caractere a l'interieur des champs XML sont pas correctement formaté:
1. quand je fait l'import dans une variable voila ce que ca donne:
[code:1]
[xml] $a = gc \"toto.inf\"
Cannot convert value \"System.Object[]\" to type \"System.Xml.XmlDocument\". Error: \"'', hexadecimal value 0x07, is an invalid character. Line 28, position 86.\"
At line:1 char:9
+ [xml] $a <<<< = gc \"toto.inf\"[/code:1]
2. en regardant le fichier il est codé en ANSI et le caractere qui apparait bizarre est au milieu du champs. j'utilise notepad++ et c'est la premiere fois que je vois ce symbole (dans le fichier attaché le BEL)
3. la ou je n'ai pas ete clair... comme je debute dans les regex (je sais c'est pas la premiere fois que je le dit dans ce forum
ce champs Name apparait plusieurs fois dans le fichier, mais la ligne qui m'interesse il y en a qu'une et c'est celle qui commence par \"Report FilterString=\"
4. l'appli qui crée les fichier est un progiciel, et il sait parfaitement utiliser ses propres fichiers. Donc coté correction j'aurais du mal à leur demandé...
5. pourquoi je fais ca c'est que l'appli lors de la creation du fichier demande le nom du rapport, elle crée le fichier inf avec ce nom et renseigne le champs \"Name=\" de la ligne avec le meme nom.
Mais ensuite cette appli, lorsqu'on renomme le rapport dans l'appli, elle ne modifie QUE le champs \"Name=\" et plus le nom du fichier. Résultat quand il s'agit de backuper les fichiers et qu'on ne veut sauvegarder que les bons, on ne peut pas s'appuyer sur le nom des rapports dans l'appli, car les fichiers physiques ont leur nom disjoint du nom du rapport qui se trouve dedans.
6. là ou j'intervient c'est que je dois recuperer le nom du rapport dans le fichier et renommer le fichier en consequence. L'appli n'utilise pas le nom du fichier elle parse tous les fichier dans le repertoire et son arborescence...
7. Ma petite regex doit etre bonne pour avoir la valeur du champs si je ne parse qu'une seule ligne. Ce qui dans mon cas ne me sert pas. Desolé de la confusion provoquée.
8. l'objectif est donc de parser tous les fichiers *.inf, de recuperer la valeur du champs \"Name=\" dans la ligne contenant \"Report FilterString=\", ensuite je fais une moulinette soit pour stocker la valeur recuerper avec le nom du fichier en face, soit renommer. sur cette derniere partie je sais plus ou moins bien faire mais je me debrouille. C'est l'extraction de la valeur qui me pose soucis.
Merci encore pour ton aide. <br><br>Message édité par: tonic8, à: 25/03/09 13:15
Pièces jointes :
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
Sont-ce toujours les mêmes ?Alors le mauvais formatage est qu'un certain nombre de caractere a l'interieur des champs XML sont pas correctement formaté:
tonic8 écrit:
C'est le caractère ascii 7, signal sonore. Saisie dans la console control-g puis enter.j'utilise notepad++ et c'est la premiere fois que je vois ce symbole (dans le fichier attaché le BEL)
Notepad t'indique pas là que c'est un caractère de control.
Avant d'aller plus loin, suite à ta réponse, ne penses-tu pas qu'une correction de ces caractères de contrôle, dans un fichier temporaire, simplifierais le pb ?
Par exemple à l'aide la function proposée ici :
powershell-scripting.com/index.php?optio...;id=4261&catid=5
Si toutefois la manipulation de XML/XPath ne te pose pas de pb particulier.
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Gabriel
-
Auteur du sujet
- Hors Ligne
- Membre elite
-
- Messages : 248
- Remerciements reçus 1
Et l'avantage c'est que je ne pase par l'ecriture d'un fichier temporaire, qui peut toujours poser probleme (pas assez de place, ou le fichier temp existe deja et autre)...
Je vais regarder tout de meme ta solution.
Merci pour ton aide.
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
Bonne approche, mais faut savoir que c'est un apprentissage sur le long terme.De mon coté je dirais que je connais un peu les regex, et c'est peut-être, à mon niveau, le sujet plus le difficile à appréhender que j'ai rencontré en informatique.Ben disons que je voulais vraiment le faire via les regex pour comprendre/apprendre les regex.
Je te conseille d'investir dans ce bouquin, Maîtrise des expressions régulières .
tonic8 écrit:
Après réflexion elle ne répond pas vraiment au besoin, c'était l'idée du filtre que je voulais mettre en avant.Je vais regarder tout de meme ta solution.
tonic8 écrit:
De rien.Merci pour ton aide.
Sinon que donne la regex que je t'ai proposée ?
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Vous êtes ici :
-
Accueil
-
forum
-
PowerShell
-
Entraide pour les débutants
- Regex pour newbie