Petit TP PowerShell facile pour une fois, sur la gestion des chaînes de caractères (ou String).
Admettons, pour commencer que l’on est fait un bout de script qui récupère les comptes machines de nos serveurs avec leurs dates de création.
Premier exercice cash ! Écrivez cette commande PowerShell avec Get-ADComputer.
Pour les autres, la solution ci-dessous très bien cachée.
PS C:\> $tab = Get-ADComputer -SearchBase 'OU=Serveurs,DC=equestria,DC=com' -SearchScope Subtree -Filter * -Properties whencreated
Bon, et si on cherche à tester les serveurs donc le nom commence par ‘Pony-‘ pour avoir nos serveurs du projet poney ? Pour commencer doucement on va le faire avec une boucle FOR.
#Ici on crée un tableau vide $srv_pony = @() #Pour chaque élément du tableau de tous les serveurs ForEach($srv in $tab){ #Si le nom commence par pony if($srv.name -match '^pony\-*'){ #On l’ajoute dans le tableau $srv_pony += $srv } }
On récupère alors les serveurs dans l’Active Directory dont le nom de machine commence par pony-. Ceux qui ne connaissent pas ont sûrement remarqué que mon « -match » est un peu étrange. En fait j’utilise la syntaxe des expressions régulières. Les expressions régulières sont avant tout un modèle théorique (utilisé en compilation par exemple) pour gérer des chaînes de caractères, ce modèle est implémenté dans la plupart des langages de programmations. On s’en sert en général pour faire du « search & replace » dans du texte.
Sans rentrer dans les détails techniques Google est votre ami pour ça, il faut lire comme suit :
La variable,
$srv.name
Est conforme avec,
-match
L’expression régulière suivante :
Commence Par '^
La chaine Pony
Pony
Suivi d’un « – »
\- *(Backslash permet d’éviter que le tiret soit interprété comme un caractère spécial, comme le `^` juste avant)*
Et qui finit par n’importe quoi.
*'
Bon, la comme ça, ça parait compliqué pour dire « commence par Pony tiret ». Mais dans la vraie vie, les expressions régulières c’est bon, y’a pas grand-chose d’aussi puissant et à peu près commun à tous les langages de programmation !
=> Donc mangez-en…
Petit encart sur les Expressions Régulières (dit RegEx) utilisés ci-dessus.
On peut faire des recherches des patterns très avancés par exemple : trouve-moi toutes les adresses IP V4 ou V6 dans un document texte :
Regex IPV4 :
La structure de l’adresse IP version 4 est très simple. Elle est constituée de 4 nombres allant de 0 à 255 séparés par un point : 1.2.3.4, soit :
(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
Exemple :
PS C:\> '127.0.0.1' –match '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' True
PS C:\> '42.12.A.666' –match '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' False
Regex IPV6 :
La structure des adresses IPv6 est plus complexe. En effet, contrairement à l’IPv4, les mêmes adresses IPv6 peuvent s’écrire différemment. Par exemple, l’adresse `0:0:0:0:0:0:0:1` est la même que l’adresse `::1`. Cette complexité se traduit par une REGEX très, très, longue et compliquée, car elle comprend les différents types d’adresse IPv6 possibles.
La voici :
((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|(([0-9A-Fa-f]{1,4}:){0,5}:((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|(::([0-9A-Fa-f]{1,4}:){0,5}((b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b).){3}(b((25[0-5])|(1d{2})|(2[0-4]d)|(d{1,2}))b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))
Et on fait moins les malins là, hein ?
Et maintenant, pour les besoins d’une application, si on a besoin de remplacer tous les Pony- de ces serveurs par des Sangliers_ et d’en faire une liste ?
PS C:\> $srv_pony.Name -replace ('^Pony\-*','Sangliers_') Sangliers_Applejack Sangliers_Pinkie-pie Sangliers_Celestia Sangliers_Rainbow-Dash Sangliers_Rarity Sangliers_Spike Sangliers_Twilight-Sparkle Sangliers_fluttershy Sangliers_Cadance Sangliers_Shining
Pour finir rapidement, PowerShell implémente les Regex via le .NET, mais on peut également utiliser le Framework .NET directement depuis PowerShell pour ça :
PS C:\> [Regex]::Replace('Peny','e','o') Pony
Voilà, j’espère vous avoir appris ou rappelé 2-3 truc.
@++