使用“foreach”解析CSV文件会在输出中生成重复条目

0g0grzrc  于 2023-01-15  发布在  其他
关注(0)|答案(1)|浏览(97)

在编写下面的PowerShell脚本以及使用循环和分支时,我遇到了一个基本问题。看起来我遗漏了一些非常简单的东西,但现在我不知道如何改进脚本。
这里有一个例子:

$mycsv = Import-Csv mycsv.csv

for ($i = 1 ; $i -le 123 ; $i++) {
    $currentvalue = "OLD"
    foreach ($value in $mycsv) {
        switch ($value.oldValue) {
            $currentvalue {
                Write-Host "Number $i - $currentvalue replaced with $($value.newValue)"
            }
            default { Write-Host "Number $i - $currentvalue unchanged" }
        }
    }
}

mycsv.csv文件包含以下三行:

oldValue,newValue
FOO,BAR
OLD,NEW
ABC,DEF

电流输出如下:

...
Number 123 - OLD unchanged
Number 123 - OLD replaced with NEW
Number 123 - OLD unchanged
...

如您所见,脚本为每个数字写入三行,这是意料之中的,因为脚本为CSV文件中的三个条目提供了foreach循环。
但是我希望脚本显示操作的状态,而不是每个条目的oldValue与newValue匹配的状态。
我需要在脚本中做什么修改才能显示“未更改”字符串或“已替换”字符串?我需要在某个地方添加break以使脚本退出foreach循环吗?还是需要用其他内容替换foreach
PS我明白我的脚本现在实际上并没有替换任何东西,它只是基于$currentvalue和CSV文件中的条目显示输出。

更新#1

我尝试基于$currentvaluemycsv.csv中的行Write-Host不同的文本。如果脚本在mycsv.csv的第一列中找到$currentvalue的值,那么它必须写入“编号1 -旧替换为新”,其中新取自CSV文件的同一行($value.newValue)。
你可以把它想象成我使用CSV文件作为一个引用,例如,如果脚本解析一个文本文件并发现单词OLD,它需要用从CSV中提取的单词NEW替换它。
我试图简化我的脚本,只留下相关的部分。它有一点多的代码,但我故意把它省略了,因为它在这个问题的上下文中并不重要。
我打算使用foreach循环遍历CSV文件中的条目,并将它们与$currentvalue匹配。当$currentvalue与CSV第一列中的条目之一匹配时,脚本需要写入“编号1 -(第一列中的单词)替换为(第二列中的单词)"。
如果没有匹配项,则脚本应写入“编号1 - $currentvalue未更改”。
因此,应该只有两种类型的输出:
“编号1 -(取自第一列的单词)替换为(取自第二列的单词)”(如果匹配)
“编号1 - $currentvalue未更改”(如果未找到匹配项)
脚本需要for循环,因为它必须迭代修订号。我将$i传递给一个命令行实用程序。我省略了脚本的这一部分,因为它在这里不重要。

xggvc2p6

xggvc2p61#

给定该测试Csv:

$csv = @'
oldValue,newValue
FOO,BAR
OLD,NEW
ABC,DEF
BAZ,BAZ
'@ | ConvertFrom-Csv

我相信你想要的是:

$csv | ForEach-Object { $idx = 1 } {
    $status = 'unchanged'
    if($_.oldValue -ne $_.newValue) {
        # if it changed assign a new value
        $status = 'replaced with {0}' -f $_.newValue
    }
    
    Write-Host ('Number {0} - {1} {2}' -f $idx++, $_.oldValue, $status)
}

它将输出:

Number 1 - FOO replaced with BAR
Number 2 - OLD replaced with NEW
Number 3 - ABC replaced with DEF
Number 4 - BAZ unchanged

我认为您应该采用面向对象的方法:

$csv | ForEach-Object {
    $status = 'unchanged'
    if($_.oldValue -ne $_.newValue) {
        # if it changed assign a new value
        $status = 'replaced with {0}' -f $_.newValue
    }

    # output a new object appending this new property
    $_ | Select-Object *, @{ N='Status'; E={ $status }}
}

它将输出:

oldValue newValue Status
-------- -------- ------
FOO      BAR      replaced with BAR
OLD      NEW      replaced with NEW
ABC      DEF      replaced with DEF
BAZ      BAZ      unchanged

相关问题