Software Development Kit (SDK) and API Discussions

newbie general powershell looping question

stephen2
6,608 Views

I have a sorted csv file in the following format:

 

name, uniqueID, environment

 

server1 x123 production

server1 x234 installed

server1 x345 n/a

server2 x999 anything

 

what I want to do is read the environment for the first occurance of server1, and then update the unique identifiers via API for any subsequent occurances of the name

 

so my expected output would be  

server1  x123  production

server1 x234   production

server1 x345   production

server2  x999 anything

etc ...

 

Anyone know what type of foreach loop with a nested loop would produce such a result?

 

thanks

 

Thanks in advance

 

1 ACCEPTED SOLUTION

asulliva
5,072 Views

No worries!  Feel free to reach out here or on Slack, we have a channel specifically for PowerShell questions.

 

Andrew

If this post resolved your issue, please help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

View solution in original post

11 REPLIES 11

asulliva
6,577 Views

Hello @stephen2,

 

Here is a quick example I created:

 

$csv = "name,id,status
server1,x123,production
server1,x234,installed
server1,x345,n/a
server2,x999,anything"

$lines = $csv | ConvertFrom-Csv

$values = @{}
$output = New-Object System.Collections.Generic.List[System.Object]

foreach ($line in $lines) {
    if ($values.Keys -notcontains $line.name) {
        $values.Add($line.name, $line.status)
    }

    $line.status = $values.($line.name)
    $output.Add($line)
}

$output

 

Hope that helps!

 

Andrew

If this post resolved your issue, please help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

stephen2
6,535 Views

Thanks Andrew - using the hash table does not help because for each record, I have to maintain the id field, so I need to accomplish the following:

 

first record, store the env field and write the server, id, and env field

subsequent record - write the server, id, and saved env

 

Is it possible to accomplist the functionality using some other structure?

asulliva
6,531 Views

Did you execute the code?  Cause I'm not sure what you mean...it outputs correctly from what I can tell:

 

name    id   status    
----    --   ------    
server1 x123 production
server1 x234 production
server1 x345 production
server2 x999 anything  

The hash is only used to store the first name -> status and keep them for later.  I'm assuming that the names are not always in order, e.g there could be another "server1" after "server2", which is why I'm using the hash to store the values.

If this post resolved your issue, please help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

stephen2
6,528 Views

I tried but I may have done something wrong. I modified as follows and got the below message

$csv = import-csv env.csv

$lines = $csv| ConvertFrom-Csv $values = @{}

$output = New-Object System.Collections.Generic.List[System.Object]

foreach ($line in $lines) {

            if ($values.Keys -notcontains $line.name) {

                        $values.Add($line.name, $line.status)

            }

            $line.status = $values.($line.name)

            $output.Add($line)

}

$output

 

ConvertFrom-Csv : Cannot validate argument on parameter 'InputObject'. The argument is null or empty. Provide an argument that is

At line:1 char:32

+ $lines = $csv| ConvertFrom-Csv $values = @{}

+                                ~~~~~~~

    + CategoryInfo          : InvalidData: (:) [ConvertFrom-Csv], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.ConvertFromCsvCommand

 

asulliva
6,526 Views

You don't need to use "Import-Csc" and "ConvertFrom-Csv", just one or the other.  If it's a file on disk, just use Import-Csv...

 

$lines = Import-Csv env.csv

$values = @{}
$output = New-Object System.Collections.Generic.List[System.Object]

foreach ($line in $lines) {
    if ($values.Keys -notcontains $line.name) {
        $values.Add($line.name, $line.status)
    }

    $line.status = $values.($line.name)
    $output.Add($line)
}

$output

If you want to output the result to a new CSV, use the ConvertTo-Csv cmdlet...

 

$output | ConvertTo-Csv -NoTypeInformation

Andrew

If this post resolved your issue, please help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

stephen2
6,522 Views

thought I tried that, but I will give it a shot again. Thanks

stephen2
6,517 Views

where does the status field come from? Do I need to add it to my input file?  Im getting this:

 

Exception setting "status": "The property 'status' cannot be found on this object. Verify that the property exists and can be set."

At line:5 char:5

+     $line.status = $values.($line.name)

+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException

    + FullyQualifiedErrorId : ExceptionWhenSetting

 

 

thank you for this help by the way

asulliva
6,515 Views

I didn't use your original field names...I may have missed them 😄

 

Using your field names it should be...

 

$lines = Import-Csv env.csv

$values = @{}
$output = New-Object System.Collections.Generic.List[System.Object]

foreach ($line in $lines) {
    if ($values.Keys -notcontains $line.name) {
        $values.Add($line.name, $line.environment)
    }

    $line.environment = $values.($line.name)
    $output.Add($line)
}

$output
If this post resolved your issue, please help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

stephen2
6,513 Views

ah - thank you - sorry Im a newbie

asulliva
5,073 Views

No worries!  Feel free to reach out here or on Slack, we have a channel specifically for PowerShell questions.

 

Andrew

If this post resolved your issue, please help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

stephen2
5,053 Views

worked perfect - thanks

Public