2
votes

I have this content in a file:

File Versions              
---- --------              
aaa  {1.0.0.123, 1.0.0.124}
bbb  {1.0.0.123, 1.0.0.124}   

How to read it in powershell into table, or typed array?

I've created the file by this script:

$versions = $dictionary | ForEach-Object{
   $properties = @{
      File =  $dictionary.Key
      Versions = $dictionary.Value <# an array of strings #> 
   }
   New-Object PSObject -Property $properties
}

$versions | Out-File "filesVersions.txt"

The script is not used anymore. It's just for demostration of what is in the filesVersions.txt file.

What I actually want is to store a key value pairs in a file, where key is FileName and Value is list of versions.

From time to time I need to read the file content, all a new row or a new version to existing row and save it back.

I wanted to use Format-Table output for it.

2
That looks like you saved Format-Table output to a file. Do you have control over that output. It would be easier to address that problem then to parse it back now. Or is it actually a CSV file and you could just use Import-CSV "filesVersions.csv". Or is this a large file and that is why you use ReadAllLines?Matt
What is $versions?Matt
See my edit with a little more explanation. It does not matter what is filesVersions.csv or $dictionary since it does not exist anymore. It's just my test data, which I saved to a file and I want to read it back.Liero
@Liero You can't (reliably) do that - how would you determine whether {1.0.0.123, 1.0.0.124} represents an array (of what? could be versions, IP addresses) or just the string literal "{1.0.0.123, 1.0.0.124}"? As @Matt said, exporting to another format in the first place is how you'd solve this problem in the real world (eg. Export-CliXml or Export-Csv instead of formatted output to Out-File).Mathias R. Jessen

2 Answers

1
votes

I wanted to use Format-Table output for it. Sorry but that is not the way you should be doing it. You are adding a lot of unnecessary overhead. You are looking at string parsing which can be unreliable and tedious.

PowerShell's power comes from objects. Using Export-CSV would be ideal in this situation. However you would need to do something with that array going both directions.

$versions = $dictionary | ForEach-Object{
   $properties = @{
      File =  $dictionary.Key
      Versions = $dictionary.Value -join "|"
   }
   New-Object PSObject -Property $properties
}

$versions | Export-Csv "filesVersions.csv" -NoTypeInformation

When you go to import the data back into PowerShell to get the objects you would need to split that field to get the array back.

Import-Csv "filesVersions.csv" | ForEach-Object{
    # Update the property
    $_.Versions = $_.Versions -split "|"
    # Send the updated object down the pipe
    $_
}

Or using a calculated property

Import-Csv "filesVersions.csv" | Select-Object File,@{Name="Versions";Expression={$_.Versions -split "|"}}

Like Mathias says you could also use Export-CLIXML and you would not need to do the join or anything. I personally think that is for more complex output then what you are doing here.

1
votes

"That is not the way you should be doing it", as @Matt wrote, is what I would like to state at first myself.
But I like to think out of the box and question what if there is:

  • a cmdlet that would be able to convert from a easy to read fixed width table?
  • a cmdlet that allows you to easy convert an embedded (object) table in your script?
  • a cmdlet that can deal with little more than just strings?

In other words: couldn't it be that in some cases a fixed width SourceTable sometimes makes more sense than an uglyfied cvs or xml table?

ConvertFrom-SourceTable

ConvertFrom-SourceTable (alias cfst) is capable reading most fixed width tables without any help. Unfortunately, the example in the question is probably not the best example: although, ConvertFrom-SourceTable is able restore (right aligned) types as e.g. integers, it is not able to restore the odd array format from the Format-Table output. Nevertheless, you can use the native Select-Object to resolve this part of the issue:

ConvertFrom-SourceTable '
    File Versions
    ---- --------
    aaa  {1.0.0.123, 1.0.0.124}
    bbb  {1.0.0.123, 1.0.0.124}
' | 
Select-Object File, @{n='Versions'; e={$_.Versions.TrimStart('{').TrimEnd('}') -Split '\s*,\s*'}}

For the latest version of ConvertFrom-SourceTable, see the PowerShell Gallery or GitHub