J'ai créé un script Powershell qui effectue un foreach sur un tableau de chaînes et ne collecte que quelques informations. Voici le code:
PS C:\Users\db> $myvar = .\BkpScript.ps1 PS C:\Users\db> $myvar Server : Srv01 Id : Srv01_999888777 CopyNumber : 2 Server : Srv01 Id : Srv01_999888777 CopyNumber : 2
Lorsque j'exécute le script, j'ai une sortie avec deux objets avec des valeurs CopyNumber différentes (résultat attendu):
PS C:\Users\db> .\BkpScript.ps1 Server : Srv01 Id : Srv01_999888777 CopyNumber : 1 Server : Srv01 Id : Srv01_999888777 CopyNumber : 2
Si j'essaye de stocker la sortie dans une variable, j'ai le même CopyNumber (résultat non attendu):
begin { $IMAGELIST = @( "IMAGE Srv01 something something something Srv01_999888777 something" "FRAG 1 something something" "FRAG 2 something something" ) } process { foreach ($LINE in $IMAGELIST) { if ($LINE.StartsWith("IMAGE")) { $IMAGELINE = $LINE.split() $BKP_OBJ = [pscustomobject]@{ Server=$IMAGELINE[1] Id=$IMAGELINE[5] } } elseif ($LINE.StartsWith("FRAG")) { $FRAGLINE = $LINE.split() $BKP_OBJ | Add-Member -Force @{ CopyNumber = $FRAGLINE[1] } Write-Output -InputObject $BKP_OBJ } } }
Qu'est-ce que je fais mal?
3 Réponses :
Je suppose que vous voulez quelque chose comme ça?
begin { $BKP_OBJ = $null $IMAGELIST = @( "IMAGE Srv01 something something something Srv01_999888777 something", "FRAG 1 something something", "FRAG 2 something something" ) } process { $Ximglist = @() $Xfrglist = @() foreach ($LINE in $IMAGELIST) { if ($LINE.StartsWith("IMAGE")) { $Ximglist += $LINE } elseif ($LINE.StartsWith("FRAG")) { $Xfrglist += $LINE } } foreach ($Ximg in $Ximglist) { $Xfrglist | % {($_.split())[1]} | % {$BKP_OBJ = [pscustomobject]@{ Server= ($Ximg.Split())[1] Id= ($Ximg.Split())[5] CopyNumber=$_ }; Write-Output $BKP_OBJ} } }
Vous pouvez enregistrer le $ BKP_OBJ
dans une variable (par exemple $ ARR_BKP_OBJ
) que vous pourrez utiliser plus tard. En faisant $ ARR_BKP_OBJ = @ ()
et $ ARR_BKP_OBJ + = $ BKP_OBJ
.
J'ai d'abord essayé d'ajouter $ BKP_OBJ à un tableau, mais lorsque j'essaie de stocker la sortie du script dans la variable $ myvar, j'obtiens le même résultat inattendu Considérez que les chaînes IMAGE et FRAG sont un ensemble d'informations que je ne peux pas traiter en deux tableaux dans un second temps, car je peux avoir plus d'un ensemble d'informations. Par exemple. "IMAGE Srv01 quelque chose quelque chose quelque chose Srv01_999888777 quelque chose" "FRAG 1 quelque chose quelque chose" "FRAG 2 quelque chose quelque chose" "IMAGE Srv02 quelque chose quelque chose quelque chose quelque chose Srv02_456734231 quelque chose" "FRAG 1 quelque chose quelque chose" "FRAG 2 quelque chose quelque chose"
On dirait que vous voulez utiliser des foreach
imbriqués? Ou (comme ma solution) un Foreach-Object
(= %
) dans une instruction foreach
.
Vous ne créez qu'un seul objet, que vous modifiez et affichez deux fois. L'instruction d'affectation la complète en premier, avant l'affichage de toute sortie. Le pointeur est le même pour les deux sorties. (. \ BkpScript) ferait la même chose.
cat myscript.ps1 $a = [pscustomobject]@{name='Joe'} $a $a.name = 'John' $a ./myscript name ---- Joe John (./myscript) # or ./myscript | sort name ---- John John
Ce code créera un nouvel objet chaque fois qu'il sera envoyé / envoyé:
PS C:\Users\db\Desktop> .\test.ps1 Server Id CopyNumber ------ -- ---------- Srv01 Srv01_999888777 1 Srv01 Srv01_999888777 2 PS C:\Users\db\Desktop> $myvar = .\test.ps1 PS C:\Users\db\Desktop> $myvar Server Id CopyNumber ------ -- ---------- Srv01 Srv01_999888777 1 Srv01 Srv01_999888777 2
Le résultat ressemble à ce que vous attendez dans votre question:
begin { $IMAGELIST = @( "IMAGE Srv01 something something something Srv01_999888777 something" "FRAG 1 something something" "FRAG 2 something something" ) } process { $Server = "" $Id = "" $CopyNumber = 0 foreach ($LINE in $IMAGELIST) { if ($LINE.StartsWith("IMAGE")) { $IMAGELINE = $LINE.split() $Server=$IMAGELINE[1] $Id=$IMAGELINE[5] } elseif ($LINE.StartsWith("FRAG")) { $FRAGLINE = $LINE.split() $CopyNumber = $FRAGLINE[1] Select-Object @{n='Server'; e={$Server}}, @{n='Id'; e={$Id}}, @{n='CopyNumber'; e={$CopyNumber}} -InputObject '' } } }
Pouvez-vous nous en dire plus sur le problème que vous essayez de résoudre avec ce script? Il contient beaucoup de choses pour le préparer pour le pipelining, par exemple, mais je ne comprends pas pourquoi. Que voulez-vous en conséquence? Une liste d'objets, une chaîne ou simplement une sortie sur le terminal?
Qu'est-ce que
$ FRAGLINE
? Vous l'utilisez comme un tableau, mais où est-il défini? De plus, si le premier test échoue, il n'y aura pas d'objet auquel ajouter la propriétéCopyNumber
.La cause première de votre problème est le fait que vous créez un objet dans le cas 1 et après cela, vous le modifiez dans le cas 2 au lieu d'en faire des copies. Par conséquent, tous les "instantanés" de votre objet seront les mêmes pointeurs qui pointent vers la dernière version modifiée.
Normalement, $ IMAGELIST est un tableau de chaînes données par une sortie de commande externe. La commande externe donne trois lignes ou plus pour chaque enregistrement unique (la première ligne est toujours IMAGE, les autres sont plus d'un FRAG) Pour chaque enregistrement unique, je dois créer un objet avec des informations de la chaîne IMAGE et des informations des chaînes FRAG. @Thomas ce que tu as dit me semble raisonnable, mais je ne peux pas comprendre complètement. Comment dois-je changer le script à votre avis?
@Theo mon erreur. J'ai édité le code
@karnak Voir ma réponse ci-dessous.
J'ai voté pour le comportement intéressant de l'objet.
@Theo parfait! Merci
Ce n'était pas moi. @Thomas a fait le travail!