IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Scripts/Batch Discussion :

Difficultés avec les regex [PowerShell]


Sujet :

Scripts/Batch

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 127
    Points : 70
    Points
    70
    Par défaut Difficultés avec les regex
    Bonjour tout le monde.

    Je débute avec le powershell et ai encore bcp de difficultés à appréhender les expressions régulières.

    J'ai une chaine de caractère à parser. celle-ci peut-être de 3 formes :

    -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Status and Counters - Address Table - 0025b3-0ec59c
    
      MAC Address : 0025b3-0ec59c
      Located on Port : F22
      blablabla
    -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Status and Counters - Address Table - 0025b3-0ec59f
    
    MAC address 0025b3-0ec59f not found.
    blablabla
    -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Status and Counters - Address Table - 0025b3-0ec59c
    
      MAC Address : 0025b3-0ec59c
      Located on Port : Trk10
    blablabla

    Dans le premier cas je cherche à récupérer le port (ici F22), il est composé de1 à 3 caractères (ici 3).

    Dans le second cas j'ai réussi à la gerer.

    Le troisième je cherche à récupérer le numéro du trk, ici la valeure 10.

    Voyez-vous comment je peux récupérer ces deux valeurs ?

    D'avance merci pour votre aide.

  2. #2
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Salut,
    Citation Envoyé par julie75 Voir le message
    Je débute avec le powershell et ai encore bcp de difficultés à appréhender les expressions régulières.
    Il s'agit de deux choses différentes, même si PowerShell supporte les regex de dotnet.
    Citation Envoyé par julie75 Voir le message
    J'ai une chaine de caractère à parser.
    D'après le texte, est-ce une chaîne ou un texte ( un tableau de chaînes ?) ?
    Citation Envoyé par julie75 Voir le message
    blablabla
    Tu veux dire par là que le reste n'a plus d'importance ? et ce reste est-il constitué d'une ou + chaînes ?
    Citation Envoyé par julie75 Voir le message
    Le troisième je cherche à récupérer le numéro du trk, ici la valeure 10.
    Voyez-vous comment je peux récupérer ces deux valeurs ?
    Les deux valeurs sont bien TRK et 10 ?
    Si oui, sont-elles tjrs codées,respectivement, sur 3 et 2 caractères ?

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 127
    Points : 70
    Points
    70
    Par défaut
    Bonjour Laurent,

    Merci une nouvelle fois pour ta réponse (tu m'as déjà bien aidé par le passé).

    D'après le texte, est-ce une chaîne ou un texte ( un tableau de chaînes ?) ?
    Il s'agit d'une chaîne (du moins je l'imagine) elle est déclarée ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $SCRIPT:output += GetOutput
    Citation:
    Envoyé par julie75 Voir le message
    blablabla
    Tu veux dire par là que le reste n'a plus d'importance ? et ce reste est-il constitué d'une ou + chaînes ?
    Effectivement, le reste n'a pas d'importance, il est composé d'espaces et d'autres chaînes sans importantes.

    J'ai réussi à récupérer le Trk mais c'est juste pas très propre, un expert comme toi va s'arracher les cheveux en voyant cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    [INT]$trk
    $output -match "\bLocated\W+(?:\w+\W+){1,6}?Trk.*\b"
    			
    $C = $matches[0][-2] + $matches[0][-1]
    
    switch -wildcard ($C) 
    { 
    				"?1" {$trk=1} 
    				"?2" {$trk=2} 
    				"?3" {$trk=3} 
    				"?4" {$trk=4} 
    				"?5" {$trk=5} 
    				"?6" {$trk=6} 
    				"?8" {$trk=8}
    				"10" {$trk=10} 
    				"34" {$trk=34} 
    				default {"The trk could not be determined."}
    }
    			
    write-host $trk
    Mais en faite je vais changer de stratégie dans mon développement, maintenant j'ai juste besoin de savoir dans lequel des 3 cas on est :

    - Cas 1 : la chaine contient "located on port..", si on est dans ce cas alors on récupère le port.
    - Cas 2 : la chaine contient "located on port : trk...".
    - Cas 3 : la chaine contient "mac address not found".

    Pour mon cas 2 je test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $outpout -match "\bLocated\W+(?:\w+\W+){1,6}?Trk.*\b"
    Il me retourne bien "true" dans le prompt mais je n'arrive pas à récupérer cette valeur (true ou false) dans une variable.

    Si tu vois comment faire pour localiser dans quel cas la chaine est je suis preneuse !

    Je cherche à coté en attendant.

    Merci encore pour tes nombreuses aides précieuses.

  4. #4
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par julie75
    J'ai réussi à récupérer le Trk mais c'est juste pas très propre
    Ce n'est pas, à mon avis, une histoire de propreté, plutot d'efficacité. Si le code répond au besoin, c'est déjà bien :-)
    Pour cette expression :
    Citation Envoyé par julie75
    $output -match "\bLocated\W+(?:\w+\W+){1,6}?Trk.*\b"
    n'ayant pas la connaissance du contexte difficile de dire quoi que soit. Si n'est que d'après les exemples cités, on peut simplifier la regex.
    Mais pour ce faire il faut connaitre le producteur du texte...
    Pour ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $C = $matches[0][-2] + $matches[0][-1]
    L'usage de capture nommée facile la lecture et la maintenance. Les évolutions surtout; si ton texte change le calcul des index peut lui aussi changer, avec une capture nommée ce n'est plus le cas, en tout cas il y a beaucoup moins d'impact.
    Citation Envoyé par julie75
    un expert comme toi va s'arracher les cheveux en voyant cela :
    Bha comme il ne m'en reste plus des masses, j'évite de me les arracher.
    Quant à l'expert, c'est toi qui me mets à cette place, et comme dirais l'autre "tout ce que je sais, c'est que je ne sais rien."
    Une raison de plus pour apprendre ;-)
    Citation Envoyé par julie75
    Mais en faite je vais changer de stratégie dans mon développement
    Bravo.
    Dans ce cas une ébauche de solution, ébauche car encore une fois le contexte, n'est pas clairement identifié, bien que précisé.
    Ceci pour dire que les regex ci dessous ne seront peut être pas adaptée, c'est juste une proposition de traitement sur le "maintenant j'ai juste besoin de savoir dans lequel des 3 cas on est :".
    Construction du jeux de texte à analyser ( à vérifier s'il correspond à ton contexte) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    $texte=@"
    Status and Counters - Address Table - 0025b3-0ec59c
    MAC Address : 0025b3-0ec59c
    Located on Port : F22
    blablabla -
    blablabla -  
    "@
    $S0= $texte -split "`n"
    $texte=@"
    Status and Counters - Address Table - 0025b3-0ec59f
    MAC address 0025b3-0ec59f not found.
    blablabla -
    "@
    $S1= $texte -split "`n"
    $texte=@"
    Status and Counters - Address Table - 0025b3-0ec59a
    MAC Address : 0025b3-0ec59a
    Located on Port : Trk10
    blablabla
    blablabla - 
    blablabla - 
    "@
    $S2= $texte -split "`n"
    De ce que j'ai compris, 2 jeux hors specs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #Adresse mac existant sans port
    $texte=@"
    Status and Counters - Address Table - 0025b3-0ec59d
    MAC Address : 0025b3-0ec59d
    blablabla
    blablabla - 
    blablabla - 
    blablabla - 
    "@
    $S3= $texte -split "`n"
    #Port existant sans Adresse mac  
    $texte=@"
    Status and Counters - Address Table - 0025b3-0ec591
    Located on Port : Trk10
    blablabla
    "@
    $S4= $texte -split "`n"
    Ma proposition de solution, proposée sur un autre forum, est construite autour d'une itération, de ligne de texte, basée sur une des capacités du switch Powershell, à savoir traiter des regex sur la valeur d'entrée.
    Le principe : sur chaque ligne à analyser j'exécute une regex, si le texte correspond on exécute un traitement. La régle est qu'on suppose les lignes ordonnées et émises par 'bloc'.
    Si on change l'ordre du 'bloc' de lignes, le code du switch s'en trouve impacté :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    $lastMacAddress=$null
    $Datas=$s0,$s1,$s2,$s3,$s4|
     Foreach {$_}|
     Foreach {
      Write-Debug "Ligne courante : $_"
      switch  -regex ($_) 
      {
        'Status and Counters - Address Table -' { 
                                                    #On crée un nouvel objet
                                                   Write-Debug "New-Object"
                                                   $Information=  New-Object psobject -property @{
                                                                          MACAddress=$null;
                                                                          MACAddressExist=$false;
                                                                          Port=$null;
                                                                          PortExist=$false;
                                                                         }
                                                   Write-Debug $information
                                                   break
                                                }
         #capture nommée
        '^MAC address : (?<MACAddress>.*)$'     {
                                                   Write-Debug "Set MACAddress"
                                                   $Information.MACAddress=$matches.MACAddress.Trim()
                                                   $Information.MACAddressExist=$True
                                                   Write-Debug $information
                                                   break
                                                }
     
        '^MAC address (?<MACAddress>.*) (?<MACAddressExist>not found.)$' {
                                                  #On renseigne la propriété MACAddress avec celle recherchée, mais
                                                  # on précise qu'elle est introuvable dans le contexte d'interrogation. 
                                                  Write-Debug "Set MACAddressExist"
                                                  Write-Debug ($matches -eq $null)
                                                  $Information.MACAddress=$matches.MACAddress.Trim()
                                                  Write-Debug $information
                                                  break
                                               }
        'Located on Port : (?<Port>.*)$'       {
                                                 #TODO parsing nom de port et numéro de port
                                                 #Dans cas la propriété 'Port' pourrait être un objet imbriqué au lieu d'une string...
                                                 Write-Debug "Set Port"
                                                 $Information.Port=$matches.Port.Trim()
                                                 $Information.PortExist=$true
                                                 Write-Debug "send info"
                                                 Write-Debug $information
                                                 $lastMacAddress=$Information.MacAddress
                                                  #Toutes les propriétés sont renseignées
                                                  #On émet l'objet dans le pipeline  
                                                 $Information
                                                 break
                                               }
       default { 
                                                 Write-Debug "Default"
                                                    #La propriétés 'Port" n'existe pas dans le texte d'origine
                                                 if ($Information.Port -eq $null) 
                                                 { 
                                                   Write-Debug "Info.Port `$null"
                                                    #$Information.MacAddress est identique pour la ou les autres 
                                                    #lignes suivant la ligne 'Located on Port'
                                                   if ($lastMacAddress -ne $Information.MacAddress) 
                                                   {
                                                      Write-Debug "send info"
                                                      #On émet l'objet dans le pipeline
                                                     $lastMacAddress=$Information.MacAddress
                                                     $Information
                                                   }
                                                 }
               }#Default
      }#Switch
    }
    $Datas
    L'ancrage des regex est à adapter.
    Il me semble que c'est une structure récurrente d'analyse de texte, provenant d'outil externe, à étudier.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 127
    Points : 70
    Points
    70
    Par défaut
    Bonjour Laurent,

    Et bien ton "ébauche de solution" est tout simplement parfaite ! Elle s'adapte complètement à mon contexte, c'est juste magnifique.

    Je n'ai pas simplement copier\coller et modifié très légèrement ta solution mais j'ai essayé de l'analyser et je trouve ça beau tout simplement.

    Par ailleurs ça m'a permis d'apprendre quelques concepts du powershell et du développement en générale.

    Donc un ENORME merci pour ton aide toujours aussi précieuse, merci pour tout ce temps passé et pour les explications détaillées.

    Pour info j'en avais besoin pour réaliser un script qui se connecte sur un stack de switchs, il repère sur quelle switch se trouve le serveur dont l'adresse Mac est passée en paramètre et met le port du switch dans le VLAN dont l'ID est passé en paramètre également.

    Voilouuuu. Merci encore et excellente soirée !

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 127
    Points : 70
    Points
    70
    Par défaut
    Hello,

    Je ressors ce "vieux" sujet car le firmware des switch a été mis à jour, du coup l'affichage est différent et je n'arrive pas à adapter la solution de Laurent (je ne pratique plus powershell).

    Maintenant nous avons les 3 cas suivants :

    Cas Bon switch :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    5412zl_Bas# show mac-address 78:ac:c0:3c:cc:10
    
     Status and Counters - Address Table - 78acc0-3ccc10
    
     Port      VLAN
     --------- ----
     G1        1
     G1        132
     G1        138
     G1        143
     G1        180
    (je voudrais récupérer G1)

    Cas autre switch :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    5412zl_Haut# show mac-address 78:ac:c0:3c:cc:10
    
     Status and Counters - Address Table - 78acc0-3ccc10
    
     Port      VLAN
     --------- ----
     Trk10     1
     Trk10     138
     Trk10     143
     Trk10     180
    Je voudrais récupérer l'info trk (je me fiche du numéro)

    Cas non connecté :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    5412zl_Haut# show mac-address 78:ac:c0:3c:cc:19
    
     Status and Counters - Address Table - 78acc0-3ccc19
    
     Port      VLAN
     --------- ----
    Je voudrais récupérer l'info "Non connecté"

    Si vous voyez comment je peux arranger la sauce, je suis preneuse (bien qu'avec le recul je me demande si c'est possible car cette solution fait de l'itération sur les lignes hors ici nous n'avons plus l'information en fin de ligne mais en début) pis bonne fin de semaine !!

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 127
    Points : 70
    Points
    70
    Par défaut
    Et bien j'ai trouvé toute seule

    C'est ultra pas propre mais ça marche :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     function GetPort2 ($SCRIPT:texte)
    {
    	[STRING]$Affichage = ""
        #write-host "Debut de la fonction GetPort2"
        $lastMacAddress=$null
    	$texte = $texte -split "`n"
    	$Datas=$texte | Foreach {$_} | Foreach {
    				  if ($Affichage -eq "ok"){
    					$p = $_ -split " "
    					$resu = $p[1]
    					if($p[1] -eq $null) {
    						$resu = "notFound"
    					}
    					$Affichage = "fin"  #On change la valeur de la variable pour ne plus rentrer dans la boucle
    
    					}
    				  
    		Write-Debug "Ligne courante : $_"
    			  switch  -regex ($_) 
    			  {
    
    				'--------- ----' {		#On enregistre le port
    				$Affichage = "ok"
    				break
    					}
    							
    
    		}
    	}
    return $resu
    }
    Si il trouve le délimiteur '--------- ----' alors il récupère le premier "mot" de la ligne suivante (tout simplement)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 10
    Dernier message: 22/10/2010, 18h37
  2. [RegEx] Problème avec les regex
    Par foffa dans le forum Langage
    Réponses: 4
    Dernier message: 31/08/2006, 14h24
  3. [RegEx] Problème avec les regex
    Par dragon noir dans le forum Langage
    Réponses: 3
    Dernier message: 24/07/2006, 11h26
  4. [C#] Difficulté avec les catch
    Par Roach- dans le forum ASP.NET
    Réponses: 9
    Dernier message: 31/01/2006, 17h57
  5. [RegEx] Pb traitement de chaînes avec les regex
    Par Invité dans le forum Langage
    Réponses: 2
    Dernier message: 25/09/2005, 00h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo