Tout d'abord, comme cela m'amène à ma question, je commencerai par noter que j'ai beaucoup travaillé avec XML dans PowerShell et que je peux facilement lire les données de fichiers XML rapidement dans des tableaux d'objets personnalisés. Par exemple, si j'avais le fichier XML suivant:
<stuff>
<item name="Joe" age="32">
<info>something about him</info>
</item>
<item name="Sue" age="29">
<info>something about her</info>
</item>
<item name="Cat" age="12">
<info>something else</info>
</item>
</stuff>
Et si je le lis simplement, comme ceci:
[xml]$myxml = Get-Content .\my.xml
Ensuite, je peux accéder à un tableau de mes éléments comme ceci:
[array]$myitems = $myxml.stuff.Item
$myitems
name age info
---- --- ----
Joe 32 something about him
Sue 29 something about her
Cat 12 something else
Alors maintenant ma question:
Comment puis-je créer une structure similaire d'un tableau d'objets personnalisés, et les initialiser dans mon script, sans lecture d'un fichier?
Je peux faire beaucoup de boucles et/ou beaucoup de création/initialisation d'objets individuels, puis ajouter des éléments à un tableau ...
Mais il semble qu'il devrait exister un moyen d'effectuer cette création/initialisation d'une manière plus simple. Notez que la clé ici est que mes objets personnalisés ont plus de deux éléments (sinon, j'aurais utilisé un hachage).
J'ai même envisagé de créer une grosse chaîne de XML et d'utiliser Select-XML, mais je ne pouvais tout simplement pas comprendre la syntaxe correctement (même si c'était le bon chemin à suivre).
Je ferais quelque chose dans ce sens:
$myitems =
@([pscustomobject]@{name="Joe";age=32;info="something about him"},
[pscustomobject]@{name="Sue";age=29;info="something about her"},
[pscustomobject]@{name="Cat";age=12;info="something else"})
Notez que cela ne fonctionne que dans PowerShell 3, mais comme vous n'avez pas mentionné la version dans votre question, je suppose que cela n'a pas d'importance pour vous.
Mettre à jour
Il a été mentionné dans les commentaires que si vous procédez comme suit:
$younger = $myitems | Where-Object { $_.age -lt 20 }
Write-Host "people younger than 20: $($younger.Length)"
Vous n'obtiendrez pas 1
comme vous pouvez vous attendre. Cela se produit lorsqu'un seul pscustomobject
est renvoyé. Cela n’est plus un problème pour la plupart des autres objets de PowerShell, car ils ont des propriétés de substitution pour Length
et Count
. Malheureusement, pscustomobject
ne le fait pas. Ceci est corrigé dans Powershell 6.1.0. Vous pouvez contourner ce problème en utilisant l'opérateur @()
:
$younger = @($myitems | Where-Object { $_.age -lt 20 })
Voici un moyen concis d'initialiser un tableau d'objets personnalisés dans PowerShell.
> $body = @( @{ Prop1="1"; Prop2="2"; Prop3="3" }, @{ Prop1="1"; Prop2="2"; Prop3="3" } )
> $body
Name Value
---- -----
Prop2 2
Prop1 1
Prop3 3
Prop2 2
Prop1 1
Prop3 3
Peut-être que tu veux dire comme ça? J'aime faire un objet et utiliser Format-Table:
PS C:\Users\Joel> $array = @()
PS C:\Users\Joel> $object = New-Object -TypeName PSObject
PS C:\Users\Joel> $object | Add-Member -Name 'Name' -MemberType Noteproperty -Value 'Joe'
PS C:\Users\Joel> $object | Add-Member -Name 'Age' -MemberType Noteproperty -Value 32
PS C:\Users\Joel> $object | Add-Member -Name 'Info' -MemberType Noteproperty -Value 'something about him'
PS C:\Users\Joel> $array += $object
PS C:\Users\Joel> $array | Format-Table
Name Age Info
---- --- ----
Joe 32 something about him
Cela mettra tous les objets que vous avez dans le tableau en colonnes en fonction de leurs propriétés.
Astuce: Utiliser -auto
permet de mieux dimensionner la table
PS C:\Users\Joel> $array | Format-Table -Auto
Name Age Info
---- --- ----
Joe 32 something about him
Vous pouvez également spécifier les propriétés que vous souhaitez dans la table. Il suffit de séparer chaque nom de propriété par une virgule:
PS C:\Users\Joel> $array | Format-Table Name, Age -Auto
Name Age
---- ---
Joe 32
Le moyen le plus simple d'initialiser un tableau
Créer un tableau
$array = @()
Créez votre en-tête
$line = "" | select name,age,phone
Remplissez la ligne
$line.name = "Leandro"
$line.age = "39"
$line.phone = "555-555555"
Ajouter une ligne à $ array
$array += $line
Résultat
$array
name age phone
---- --- -----
Leandro 39 555-555555
Voici une version plus concise de la réponse acceptée qui évite de répéter les identifiants NoteProperty et le [pscustomobject]
- cast:
$myItems = ("Joe",32,"something about him"), ("Sue",29,"something about her")
| ForEach-Object {[pscustomobject]@{name = $_[0]; age = $_[1]; info = $_[2]}}
Résultat:
> $myItems
name age info
---- --- ----
Joe 32 something about him
Sue 29 something about her
Utilisez un "Here-String" et convertissez au format XML.
[xml]$myxml = @"
<stuff>
<item name="Joe" age="32">
<info>something about him</info>
</item>
<item name="Sue" age="29">
<info>something about her</info>
</item>
<item name="Cat" age="12">
<info>something else</info>
</item>
</stuff>
"@
[array]$myitems = $myxml.stuff.Item
$myitems
Je devais créer un tableau d'un type prédéfini et j'ai réussi à faire ce qui suit:
[System.Data.DataColumn[]]$myitems = ([System.Data.DataColumn]("col1"),
[System.Data.DataColumn]("col2"), [System.Data.DataColumn]("col3"))
Compte tenu des données ci-dessus, voici comment je procéderais:
# initialize the array
[PsObject[]]$people = @()
# populate the array with each object
$people += [PsObject]@{ Name = "Joe"; Age = 32; Info = "something about him" }
$people += [PsObject]@{ Name = "Sue"; Age = 29; Info = "something about her" }
$people += [PsObject]@{ Name = "Cat"; Age = 12; Info = "something else" }
Le code ci-dessous fonctionnera même si vous ne disposez que d'un élément après un Where-Object
:
# display all people
Write-Host "People:"
foreach($person in $people) {
Write-Host " - Name: '$($person.Name)', Age: $($person.Age), Info: '$($person.Info)'"
}
# display with just 1 person (length will be empty if using 'PSCustomObject', so you have to wrap any results in a '@()' as described by Andrew Savinykh in his updated answer)
$youngerPeople = $people | Where-Object { $_.Age -lt 20 }
Write-Host "People younger than 20: $($youngerPeople.Length)"
foreach($youngerPerson in $youngerPeople) {
Write-Host " - Name: '$($youngerPerson.Name)'"
}
Résultat:
People:
- Name: 'Joe', Age: 32, Info: 'something about him'
- Name: 'Sue', Age: 29, Info: 'something about her'
- Name: 'Cat', Age: 12, Info: 'something else'
People younger than 20: 1
- Name: 'Cat'