Question Re:[fonction] New-PSCustomObjectFunction (Dynamisme)

Plus d'informations
il y a 4 ans 2 mois - il y a 2 mois 2 semaines #23250 par Laurent Dardenne
Nouvelle version de New-MatchesObject, elle gère mnt les captures optionnelles :
function New-MatchesObject{
#v2

#A partir d'une chaîne de caractères,
#construit un objet personnalisé à l'aide d'une regex
#utilisant des captures nommées.

#Exemple :
# #hashtable de paramètrages
# $MyObject=@{
# #hashtable de création d'objets
# SMB=@{
#  #Ces entrées portent les mêmes noms
#  #que les paramètres de la fonction New-MatchesObject.
#  #Ce qui autorise le splatting
#
#  #Hashtable de création d'un objet
#  #Exemple : analyse d'attribut AD extensionAttributeN
#  Res_CN=@{
#   #Nom du type affiché par Get-member ou $Variable.PsObject.TypeNames
#   TypeName='MY.SMB.Res_CN'
#    #Expression régulière contenant des captures nommées
#    #celles-ci seront utilisées pour construire des propriètés d'objets PS personnalisés
#   Regex='^extensionAttribute(?<Type>1)#CN=(?<CN>.*?),'
#    #On supprime dans la variable automatique $Matches les clés indiquées
#   Keys=0,1
#  }
#
#  Res_DN=@{
#   TypeName='MY.SMB.Res_DN'
#   Regex='^extensionAttribute(?<Type>1)#(?<DistinguishedName>.*$)'
#   Keys=0,1
#  }
# };
#  #Others=@{...}
#
# }#$MyObject
#
# $S="extensionAttribute1#CN=MyCN,..."
#
# #Le splatting ne fonctionne avec @Myobject.SMB.Res_CN
# $Parameters=$Myobject.SMB.Res_CN
# $o=New-MatchesObject $S @Parameters
# $o|gm
# $O
#
# $S2="extensionAttribute1#MyDN"
# $Parameters=$Myobject.SMB.Res_DN
# $o2=New-MatchesObject $S2 @Parameters
# $o2|gm
# $O2

param (
   #Objet sur lequel on exécute la regex
  [Parameter(Mandatory=$true,position=0)]
  [ValidateNotNullOrEmpty()]
 $InputObject,

   #Nom du type de l'objet PS
  [Parameter(Mandatory=$true,position=1)]
  [ValidateNotNullOrEmpty()]
 [String] $TypeName,

   #Expression régulière appliquée sur le paramètre InputObject
  [Parameter(Mandatory=$true,position=2)]
  [ValidateNotNullOrEmpty()]
 [String] $Regex,

   #En cas de succès de la regex,
   #on supprime les noms de clé indiquées dans la hashtable $Matches
   #celles-ci sont des groupes de capture
  [Parameter(Mandatory=$false,position=3)]
  [ValidateNotNullOrEmpty()]
   #la clé 0 contient l'intégralité de ligne analysée
  [Object[]] $Keys=0
)

Function Select-NamedCapture {
 #Extrait les noms de capture présent dans la regex
 Param( [string] $RegexStr )
 $Pattern='\?\<(.*?)\>'
 $Regex = new-object regex $Pattern

 $CurrentMatch = $Regex.match($RegexStr)

 if (!$CurrentMatch.Success)
 { Write-debug "Echec :$RegexStr" }
 else
 { $CurrentMatch.Groups[1].Value }

 while ($CurrentMatch.Success)
 {
  $CurrentMatch = $CurrentMatch.NextMatch()
  if ($CurrentMatch.Success)
  { $CurrentMatch.Groups[1].Value }
 }
}#Select-NamedCapture

Write-debug "New-MatchesObject"

$NamesOfCaptures=Select-NamedCapture -RegexStr $Regex
if ($InputObject -match $Regex)
{
   #Conflit possible entre un nom de capture numérique ('1') et le numéro d'un groupe : 1
   #dans ce cas on 'perd la capture :
   # #$Str="^(?<11>toto) (titi)"
   # $Str="^(?'1'toto) (titi)"
   # 'toto titi' -match $str
  Write-Debug "$($matches.GetEnumerator()|% {"{0}={1}" -f $_.key,$_.Value})"

  $Keys|
   Foreach {
     Write-Debug "Remove key : $_"
      #Pour les captures optionnelles,
      #si la clé n'existe pas il n'y a pas d'erreur
    $matches.Remove($_)
   }
 
     #Si des captures sont optionnelles, exemple "^(?<Vide>(ab){0,1})",
     # on compléte les propriétés manquantes. todo redondant ? $Matches contient la capture 'vide'
   Compare-Object ([string[]]$Matches.Keys) $NamesOfCaptures|
    Select -ExpandProperty InputObject|
    Foreach-Object {
       Write-Debug "Add optionnal key : $_"
      $Matches.Add($_,$Null)
    }

   Write-debug "Construction d'un objet de type : $($TypeName)"
   $Object=New-Object PSCustomObject -Property $Matches
   $Object.PsObject.TypeNames.Insert(0,$TypeName)
   Write-Output $Object
  } #sinon on ne renvoi pas d'objet ayant toutes ses propriété à $null
} #New-MatchesObject


$InfArchitecture=@{
  TypeName='INF.Architecture'
  Regex='^(?<ManufacturerName>.*?),nt(?<Architecture>.*?)\.(?<OSMajorVersion>.*?)\.(?<OSMinorVersion>.*?)((\.(?<ProductType>.*?))?(\.(?<SuiteMask>.*?))?)$'
  Keys=0,1,2,3,4
}

$Manufacturer='AMD,NTx86.6.2'

$O=New-MatchesObject $Manufacturer @InfArchitecture
$O
$O|gm


$Manufacturer=@(
 'AMD,NTx86.6.2'
 'AMD,NTx86.6.2.5'
 'AMD,NTx86.6.2.5.9'
 'AMD,NTx86.6.2.0x0000001'
 'AMD,NTx86.6.2.0x0000001.0x00000002'
 'AMD,NTx86.6.2.0x00000002'
)

$Manufacturer |Foreach-Object { New-MatchesObject $_ @INfArchitecture}
Pour le dernier exemple tous les objets personnalisés ont la même structure, les captures optionnelles sont remplacées par des propriété aynt une valeur $null.

Tutoriels PowerShell
Dernière édition: il y a 2 mois 2 semaines par Laurent Dardenne. Raison: formatage

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 3 semaines 7 heures - il y a 3 semaines 7 heures #30829 par Laurent Dardenne
Autre construction possible basée sur des variables déclarée via 'PipelineVariable' :
function New-SimplePSObject{
Param(
[string[]] $Property
)
$O=[PSCustomObject]::New()
#Suppose qu'il existe dans l'appelant une variable du nom de la propriété
#Sinon la propriété contiendra $null
$Property|
ForEach-Object {
$Value=(Get-Variable $_ -ErrorAction SilentlyContinue).Value
Add-Member -InputObject $O -MemberType NoteProperty -Name $_ -Value $Value
}
$O
}

L''exemple suivant recherche dans des fichiers de log d'une application, les sessions qui ne sont à priori pas close :
# Date à 0h:0m:0s
$Now=[datetime]::now.Date
$List=Get-ChildItem c:\projet\Logs\*.log|
Where-Object { $_.LastAccessTime.Date -eq $Now }

$FileInfo=foreach ($CurrentFile in $List){
Get-Content $CurrentFile|
Select-Object -Last 1 -PipelineVariable Line|
Select-String -Pattern "Close with exit code '0'" -NotMatch -Quiet|
Foreach-Object {
New-SimplePSObject Line,CurrentFile,NotExist
}
}

$FileInfo|Format-List

Les variables contextuelles 'Line' et 'CurrentFile' sont recopiées dans un objet personnalisé émis dans le pipeline.

Tutoriels PowerShell
Dernière édition: il y a 3 semaines 7 heures par Laurent Dardenne.

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.129 secondes
Propulsé par Kunena