【问题标题】:Add a column to a csv file and fill up new column based on an existing column powershell将列添加到 csv 文件并根据现有列 powershell 填充新列
【发布时间】:2021-04-01 14:35:52
【问题描述】:

我一直在尝试向 csv 文件添加新列,并根据现有列中的值填充新列。

我有一张这样的桌子:

|name  | number | state | desc|
| ---- | ------ |-------|-----|
|a     |  1     |  n    |   i |
|b     |  2     |  n    |   j |
|c     |  3     |  l    |   j |
|d     |  4     |  m    |   k |

我想添加一个新的列数据并根据与数组匹配的数字列填充它。

这是我目前的代码:

$a=("a","b","c")
$b=("p","q","r")
.
.
.
$c= import-csv -Path "C:\..."

$b |where-object {filtered the file based on some criteria}| select-object number, state, desc, @{Name="data"; Expression={Foreach-object {if ($_.number in $a){$_data = "x"} 
elseif($_.number in $b){$_.data = "y"}.......} | export-csv -notypeinformation -path "C:\...."

脚本运行但不填充新列。请帮忙

【问题讨论】:

    标签: powershell csv


    【解决方案1】:

    你的想法是对的。 Import-Csv 将生成一个对象数组,您可以使用Select-Object 添加计算属性,然后再次通过管道传递给Export-Csv。但是,从描述或示例代码中并不清楚表达式应该是什么。您想如何定义新的“数据”属性?

    现在我将使用我们拥有的东西。数组变量$a & $b 永远不会匹配任何东西。您也不能像那样使用ForEach-Object,也不能分配给$data 工作。 Expression 脚本块的返回值被分配给您命名为 data 的属性。下面的例子说明了这一点:

    $a = ( "1", "2", "3")
    $b = ( "4", "5", "6")
    
    Import-Csv -Path "C:\temp\12-22-20.csv"|
    Select-Object number, state, desc,
        @{Name = 'Data'; Expression = { If( $_.Number -in $a ){ 'x' } elseif( $_.Number -in $b ){ 'y' } Else { $null }}} |
    Export-Csv -Path "C:\temp\12-22-20_New.csv" -NoTypeInformation
    

    生成的 Csv 文件如下所示:

    number state desc Data
    ------ ----- ---- ----
    1      n     i    x
    2      n     j    x
    3      l     j    x
    4      m     k    y
    

    更新:使用添加成员的示例

    您不需要使用循环来添加属性:

    $a = ( "1", "2", "3")
    $b = ( "4", "5", "6")
    
    Import-Csv -Path "C:\temp\12-22-20.csv" |
    Add-Member -MemberType ScriptProperty -Name "data" -Value { If( $this.Number -in $a ){ 'x' } elseif( $this.Number -in $b ){ 'y' } Else { $null }} -PassThru |
    Export-Csv -Path C:\temp\12-22-20_New.csv -NoTypeInformation
    

    通过使用 ScriptProperty 的 MemberType,我们可以对脚本块进行轻微修改,将 $_ 替换为 $this 管道是一个隐式循环。我不确定使用 ScriptProperty 是否有任何不利之处,但这会按预期导出。这种方法不需要将输出存储在 $c 中,但如果愿意,-PassThru 会促进这一点。

    99% 的时间Select-Object 用于此目的。我知道的唯一区别Select-Object 将对象转换为 PSCustomObjects。 Get-Member 将保留底层类型,但是 Import-Csv 首先只输出 PSCustomObjects,因此这里没有影响。

    【讨论】:

    • 非常好!我喜欢它。
    【解决方案2】:

    尝试遍历 $c 导入对象数组并将新属性添加到所有对象。您要确保新列存在于所有对象中。您可以像示例中那样使用Select-Object,也可以使用Add-Member 将其添加到导入的对象中。

    $a=("a","b","c")
    $b=("p","q","r")
    ...
    $c = Import-Csv -Path "C:\..."
    
    $c | ForEach-Object {
        $value = ""
        # custom logic for value of "data"
        # if (...) { $value = ... } 
        $_ | Add-Member -MemberType NoteProperty -Name "data" -Value $value
    }
    
    $c | Export-Csv -NoTypeInformation -path "C:\...."
    

    【讨论】:

    • 干得好。我对其进行了重构以删除循环,并在我的答案中添加了一个示例。让我知道你的想法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-22
    • 2020-03-30
    • 1970-01-01
    • 2013-01-18
    • 2016-11-24
    相关资源
    最近更新 更多