使用 StreamReader 在每行的多个列上复制 Vlookup 的问题
Issue using StreamReader to replicate Vlookup on multiple columns per row
我有一个非常大的竖线分隔文件(约百万行),其中包含 11 列,其中 8 列包含一个键。
Master_File.csv
Year|Key1|Key2|Key3|Key4|Key5|Key6|Key7|Key8|Location|Name
2019|1235|2345|1231|1235|3536|1231|1234|3624|Site6|Storage
2019|2345|2345|1231|1231|3536|1235|1234|1231|Site8|Storage
2019|3536|2345|3536|1235|2345|1235|3536|1235|Site7|Storage
2019|2345|1235|1231|1235|1231|3452|1231|2345|Site9|Storage
我有另一个用竖线分隔的小文件(~8k 行),其中包含 2 列、键和值。
Lookup_File.csv
Key|Value
1235|Value 1235
2345|Value 2345
1231|Value 1231
1234|Value 1234
3536|Value 3536
3452|Value 3452
1234|Value 1234
3624|Value 3624
我需要遍历 Master_File.csv 的每一行并将键替换为 Lookup_File.csv 中的值。结果应该是这样的。
Year|Key1|Key2|Key3|Key4|Key5|Key6|Key7|Key8|Location|Name
2019|Value 1235|Value 2345|Value 1231|Value 1235|Value 3536|Value 1231|Value 1234|Value 3624|Site6|Storage
2019|Value 2345|Value 2345|Value 1231|Value 1231|Value 3536|Value 1235|Value 1234|Value 1231|Site8|Storage
2019|Value 3536|Value 2345|Value 3536|Value 1235|Value 2345|Value 1235|Value 3536|Value 1235|Site7|Storage
2019|Value 2345|Value 1235|Value 1231|Value 1235|Value 1231|Value 3452|Value 1231|Value 2345|Site9|Storage
下面的代码是我到目前为止的代码,但问题是它只运行了 Master_File 一次,只替换了第一个键。
$content = "c:\Lookup_File.csv"
$LookupFile = New-Object -TypeName System.IO.StreamReader - ArgumentList $content
$skip1 = $LookupFile.ReadLine()
$src = "c:\Master_File.csv"
$MasterFile = New-Object -TypeName System.IO.StreamReader -ArgumentList $src
$header = $Masterfile.ReadLine()
$outData = New-Object -TypeName System.Text.StringBuilder
[void]$outData.AppendLine($header)
while ($line = $LookupFile.ReadLine())
{
$key = ($line -split "\|")[0]
$value = ($line -split "\|")[1]
while ($row = $MasterFile.ReadLine()){
$row = $row -Replace $key, $value
[void]$outData.AppendLine($row)
}
}
$outData.ToString() | Out-File -FilePath "c:\Master_File_Out.csv" -Encoding ascii
我得到这个作为输出。
Year|Key1|Key2|Key3|Key4|Key5|Key6|Key7|Key8|Location|Name
2019|Value 1235|2345|1231|Value 1235|3536|1231|1234|3624|Site7|Storage
2019|2345|2345|1231|1231|3536|Value 1235|1234|1231|Site8|Storage
2019|3536|2345|3536|Value 1235|2345|Value 1235|3536|Value 1235|Site9|Storage
2019|2345|Value 1235|1231|Value 1235|1231|3452|1231|2345|Site11|Storage
我真的很难遍历 Master_File 的每一行并用值替换 8 个键中的每一个。
如有任何帮助,我们将不胜感激!
根据我的评论,尝试:
## Q:\Test19\SO_57659677.ps1
$hash = @{}
Import-Csv '.\Lookup_File.csv' -Delimiter '|' | ForEach {$Hash[$_.Key]=$_.Value}
$Master = Import-Csv '.\Master_File.csv' -Delimiter '|'
ForEach($Item in $Master){
For($i=1;$i -le 8;$i++){
if($hash.ContainsKey($item."Key$i")){
$item."Key$i" = $hash[$item."Key$i"]
}
}
}
$Master |ft -auto
# $Master | Export-Csv "c:\Master_File_Out.csv" -Delimiter '|' -NoTypeInformation
# To have no double quotes in the ouptput file
# ($Master | ConvertTo-Csv -Delimiter '|' -NoTypeInformation) -replace '"' | Set-Content -"c:\Master_File_Out.csv" Encoding ascii
示例输出:
> $Master|ft -auto
Year Key1 Key2 Key3 Key4 Key5 Key6 Key7 Key8 Location
---- ---- ---- ---- ---- ---- ---- ---- ---- --------
2019 Value 1235 Value 2345 Value 1231 Value 1235 Value 3536 Value 1231 Value 1234 Value 3624 Site6
2019 Value 2345 Value 2345 Value 1231 Value 1231 Value 3536 Value 1235 Value 1234 Value 1231 Site8
2019 Value 3536 Value 2345 Value 3536 Value 1235 Value 2345 Value 1235 Value 3536 Value 1235 Site7
2019 Value 2345 Value 1235 Value 1231 Value 1235 Value 1231 Value 3452 Value 1231 Value 2345 Site9
编辑
通过将 ColumnNames 读入数组并使用索引 1..8 添加了一个抽象级别
## Q:\Test19\SO_57659677_2.ps1
$hash = @{}
Import-Csv '.\Lookup_File.csv' -Delimiter '|' | ForEach {$Hash[$_.Key]=$_.Value}
$Master = Import-Csv '.\Master_File.csv' -Delimiter '|'
$ColNames = $Master[0].psobject.properties.name
ForEach($Item in $Master){
For($i=1;$i -le 8;$i++){
if($hash.ContainsKey($item."$($ColNames[$i])")){
$item."$($ColNames[$i])" = $hash[$item."$($ColNames[$i])"]
}
}
}
$Master |ft -auto
> .\SO_57659677_2.ps1
Year Working Approved Rejected WhatIf1 Whatif2 Submitted Proposed Syncd Location
---- ------- -------- -------- ------- ------- --------- -------- ----- --------
2019 Value 1235 Value 2345 Value 1231 Value 1235 Value 3536 Value 1231 Value 1234 Value 3624 Site6
2019 Value 2345 Value 2345 Value 1231 Value 1231 Value 3536 Value 1235 Value 1234 Value 1231 Site8
2019 Value 3536 Value 2345 Value 3536 Value 1235 Value 2345 Value 1235 Value 3536 Value 1235 Site7
2019 Value 2345 Value 1235 Value 1231 Value 1235 Value 1231 Value 3452 Value 1231 Value 2345 Site9
几乎一样。
$hash=@{}
import-csv lookup_file.csv -delimiter '|' | foreach {
$hash[$_.key] = $_.value
}
import-csv master_file.csv -delimiter '|' | foreach {
foreach ($i in 1..8) {
$_."key$i" = $hash[$_."key$i"]
}
$_
} | export-csv master_file_out.csv -delimiter '|'
我有一个非常大的竖线分隔文件(约百万行),其中包含 11 列,其中 8 列包含一个键。
Master_File.csv
Year|Key1|Key2|Key3|Key4|Key5|Key6|Key7|Key8|Location|Name
2019|1235|2345|1231|1235|3536|1231|1234|3624|Site6|Storage
2019|2345|2345|1231|1231|3536|1235|1234|1231|Site8|Storage
2019|3536|2345|3536|1235|2345|1235|3536|1235|Site7|Storage
2019|2345|1235|1231|1235|1231|3452|1231|2345|Site9|Storage
我有另一个用竖线分隔的小文件(~8k 行),其中包含 2 列、键和值。
Lookup_File.csv
Key|Value
1235|Value 1235
2345|Value 2345
1231|Value 1231
1234|Value 1234
3536|Value 3536
3452|Value 3452
1234|Value 1234
3624|Value 3624
我需要遍历 Master_File.csv 的每一行并将键替换为 Lookup_File.csv 中的值。结果应该是这样的。
Year|Key1|Key2|Key3|Key4|Key5|Key6|Key7|Key8|Location|Name
2019|Value 1235|Value 2345|Value 1231|Value 1235|Value 3536|Value 1231|Value 1234|Value 3624|Site6|Storage
2019|Value 2345|Value 2345|Value 1231|Value 1231|Value 3536|Value 1235|Value 1234|Value 1231|Site8|Storage
2019|Value 3536|Value 2345|Value 3536|Value 1235|Value 2345|Value 1235|Value 3536|Value 1235|Site7|Storage
2019|Value 2345|Value 1235|Value 1231|Value 1235|Value 1231|Value 3452|Value 1231|Value 2345|Site9|Storage
下面的代码是我到目前为止的代码,但问题是它只运行了 Master_File 一次,只替换了第一个键。
$content = "c:\Lookup_File.csv"
$LookupFile = New-Object -TypeName System.IO.StreamReader - ArgumentList $content
$skip1 = $LookupFile.ReadLine()
$src = "c:\Master_File.csv"
$MasterFile = New-Object -TypeName System.IO.StreamReader -ArgumentList $src
$header = $Masterfile.ReadLine()
$outData = New-Object -TypeName System.Text.StringBuilder
[void]$outData.AppendLine($header)
while ($line = $LookupFile.ReadLine())
{
$key = ($line -split "\|")[0]
$value = ($line -split "\|")[1]
while ($row = $MasterFile.ReadLine()){
$row = $row -Replace $key, $value
[void]$outData.AppendLine($row)
}
}
$outData.ToString() | Out-File -FilePath "c:\Master_File_Out.csv" -Encoding ascii
我得到这个作为输出。
Year|Key1|Key2|Key3|Key4|Key5|Key6|Key7|Key8|Location|Name
2019|Value 1235|2345|1231|Value 1235|3536|1231|1234|3624|Site7|Storage
2019|2345|2345|1231|1231|3536|Value 1235|1234|1231|Site8|Storage
2019|3536|2345|3536|Value 1235|2345|Value 1235|3536|Value 1235|Site9|Storage
2019|2345|Value 1235|1231|Value 1235|1231|3452|1231|2345|Site11|Storage
我真的很难遍历 Master_File 的每一行并用值替换 8 个键中的每一个。
如有任何帮助,我们将不胜感激!
根据我的评论,尝试:
## Q:\Test19\SO_57659677.ps1
$hash = @{}
Import-Csv '.\Lookup_File.csv' -Delimiter '|' | ForEach {$Hash[$_.Key]=$_.Value}
$Master = Import-Csv '.\Master_File.csv' -Delimiter '|'
ForEach($Item in $Master){
For($i=1;$i -le 8;$i++){
if($hash.ContainsKey($item."Key$i")){
$item."Key$i" = $hash[$item."Key$i"]
}
}
}
$Master |ft -auto
# $Master | Export-Csv "c:\Master_File_Out.csv" -Delimiter '|' -NoTypeInformation
# To have no double quotes in the ouptput file
# ($Master | ConvertTo-Csv -Delimiter '|' -NoTypeInformation) -replace '"' | Set-Content -"c:\Master_File_Out.csv" Encoding ascii
示例输出:
> $Master|ft -auto
Year Key1 Key2 Key3 Key4 Key5 Key6 Key7 Key8 Location
---- ---- ---- ---- ---- ---- ---- ---- ---- --------
2019 Value 1235 Value 2345 Value 1231 Value 1235 Value 3536 Value 1231 Value 1234 Value 3624 Site6
2019 Value 2345 Value 2345 Value 1231 Value 1231 Value 3536 Value 1235 Value 1234 Value 1231 Site8
2019 Value 3536 Value 2345 Value 3536 Value 1235 Value 2345 Value 1235 Value 3536 Value 1235 Site7
2019 Value 2345 Value 1235 Value 1231 Value 1235 Value 1231 Value 3452 Value 1231 Value 2345 Site9
编辑
通过将 ColumnNames 读入数组并使用索引 1..8 添加了一个抽象级别
## Q:\Test19\SO_57659677_2.ps1
$hash = @{}
Import-Csv '.\Lookup_File.csv' -Delimiter '|' | ForEach {$Hash[$_.Key]=$_.Value}
$Master = Import-Csv '.\Master_File.csv' -Delimiter '|'
$ColNames = $Master[0].psobject.properties.name
ForEach($Item in $Master){
For($i=1;$i -le 8;$i++){
if($hash.ContainsKey($item."$($ColNames[$i])")){
$item."$($ColNames[$i])" = $hash[$item."$($ColNames[$i])"]
}
}
}
$Master |ft -auto
> .\SO_57659677_2.ps1
Year Working Approved Rejected WhatIf1 Whatif2 Submitted Proposed Syncd Location
---- ------- -------- -------- ------- ------- --------- -------- ----- --------
2019 Value 1235 Value 2345 Value 1231 Value 1235 Value 3536 Value 1231 Value 1234 Value 3624 Site6
2019 Value 2345 Value 2345 Value 1231 Value 1231 Value 3536 Value 1235 Value 1234 Value 1231 Site8
2019 Value 3536 Value 2345 Value 3536 Value 1235 Value 2345 Value 1235 Value 3536 Value 1235 Site7
2019 Value 2345 Value 1235 Value 1231 Value 1235 Value 1231 Value 3452 Value 1231 Value 2345 Site9
几乎一样。
$hash=@{}
import-csv lookup_file.csv -delimiter '|' | foreach {
$hash[$_.key] = $_.value
}
import-csv master_file.csv -delimiter '|' | foreach {
foreach ($i in 1..8) {
$_."key$i" = $hash[$_."key$i"]
}
$_
} | export-csv master_file_out.csv -delimiter '|'