1
votes

Pourquoi est-ce que j'obtiens un résultat différent lorsque je stocke dans une variable mon script PS?

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?


9 commentaires

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!


3 Réponses :


0
votes

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}
        }
    }


3 commentaires

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 .



0
votes

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


0 commentaires

1
votes

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 ''
        }
    }
}


0 commentaires