ForEach を介して実行し、Index を探してオブジェクトを作成し、再び Index に到達するまでメンバーを追加します。この時点で、前のオブジェクトが出力され、新しいオブジェクトが開始されます。その後、最後のオブジェクトを配列に追加すると、設定が完了します。次に、CSVなどに出力します。
$RawData = Get-Content C:\Path\To\input.txt
$Record = ""
$Array = $RawData | Where{$_ -Match "(.+?):(.+)"} | ForEach{If($Matches[1] -eq "Index"){if(![string]::IsNullOrWhiteSpace($Record)){$Record};$Record = [PSCustomObject]@{"Index"=$Matches[2].trim()}}Else{Add-Member -InputObject $Record -MemberType NoteProperty -Name $Matches[1] -Value $Matches[2].trim()}}
$Array += $Record
$Props = $Array | ForEach{$_ | Get-Member -MemberType Properties | Select -Expand Name} | Select -Unique
$Props | Where{($Array[0]|Get-Member -MemberType Properties | Select -Expand Name) -notcontains $_} | ForEach{$Array[0]|Add-Member $_ $null}
$Array | Export-Csv C:\Path\To\File.csv -NoTypeInformation
編集:最初のレコードにフィールドがない場合 (たとえば、LastName がない場合)、次のレコードのいずれにもそのフィールドが表示されないという落とし穴が最初の回答にあることに気付きました。各レコードからすべての一意のフィールドのリストを取得し、欠落しているフィールドを null 値を持つ最初のレコードに追加することで、これを修正しました。
Edit2:パトリックの回答と私の回答の両方を見た後、彼のほうがはるかに高速に実行されることに気付いたので、両方の回答を組み合わせた修正版を作成しました。彼から取られたオブジェクト作成のいくつかのテクニックと、私のものから取られた行解析:
$RawData = Get-Content 'C:\temp\input.txt'
$Record = ""
$Array = @()
$Props = $RawData -replace "(.+?):.*","`$1"|select -Unique
ForEach($Line in $RawData){
$Line -Match "(.+?):(.+)" | Out-Null
If($Matches[1] -eq "Index"){
If([string]::IsNullOrEmpty($Array[0])){$Array = @($Record)}else{$Array += $Record}
$Record = ""|Select -Property $Props
$Record.Index = $Matches[2].trim()
}Else{
$Record.($matches[1]) = $Matches[2].trim()
}
}
$Array | Export-Csv 'C:\temp\export2.csv' -NoTypeInformation