【问题标题】:How to compare, match, and append multiple values in multiple CSV files?如何比较、匹配和附加多个 CSV 文件中的多个值?
【发布时间】:2016-03-18 00:04:25
【问题描述】:

我正在尝试找出最好的方法来做到这一点,但我不确定如何通过同一管道使用 2 个不同的文件 Import-Csv 并导出找到的值...

让我们从 CSV 文件 1 开始:我只想要 LoginNumber 的值,其中 Type = H and (ContractorDomain -ne $null -or ContractorDomain -ne "")。例如,这应该只从下面提取值 00314822167312

注意:我只是添加了空格和箭头,以便在此处作为列更易于阅读。 csv 文件的列值或箭头之间没有空格。

"LoginNumber","Type","ContractorDomain"
"0031482"    ,"H"   ,"P12345"  <<
"1251632"    ,"P"   ,"A52671"
"2167312"    ,"H"   ,"425126"  <<
"0598217"    ,"L"   ,""
"1405735"    ,"H"   ,""
"2058194"    ,"A"   ,"L21514"

当找到LoginNumber 的值编号(基于上述条件)时,在CSV 文件2 中搜索它。然后获取AccountStatusSamAccountName 的值以获取UserIDNumber 的各自值。

"SamAccountName","UserIDNumber","AccountDescriptionDetails","AccountStatus"
"jd12395"       ,"0052142"     ,"Company CEO"              ,"Enabled"
"jwet"          ,"2167312"     ,"Software Developer"       ,"Disabled"  <<
"1b3gas5"       ,"1385293"     ,"Project Manager"          ,"Disabled"
"632g1fsa"      ,"0031482"     ,"QA Tester"                ,"Enabled"   <<
"4126hs"        ,"0000418"     ,"Program Manager"          ,"Disabled"
"axv"           ,"1840237"     ,"Accountant Administrator" ,"Disabled"

对于第三个 CSV 文件,我们有以下内容:

"domainName","SameAccountName","DateExpired"
"TempDomain","jwet"           ,"20151230"    <<
"PermDomain","p21942"         ,""
"PermDomain","qz231034"       ,""
"TempDomain","632g1fsa"       ,"20151231"    <<
"TempDomain","ru20da2bb22"    ,"20160425"

接下来,对于第 3 个文件,我想添加列以插入 DisabledEnabled 值(或 User Match Not Found 值):

"domainName","SameAccountName","DateExpired","UserStatus"
"TempDomain","jwet"           ,"20151230"   ,"Disabled"               <<
"PermDomain","p21942"         ,""           ,"User Match Not Found"
"PermDomain","qz231034"       ,""           ,"User Match Not Found"
"TempDomain","632g1fsa"       ,"20151231"   ,"Enabled"                <<
"TempDomain","ru20da2bb22"    ,"20160425"   ,"User Match Not Found"

我学会了如何导入 csv 并使用类似的东西创建新列...

Import-Csv $file | Select-Object -Property *, @{Name="UserStatus";Expression={
  if ($true) {"fill value in here"}
}} | Export-Csv $newFile -NoType

所以我在想这样的事情。我只是不确定如何通过管道搜索/查找/传递多个 CSV 文件值。

注意:其中一些 CSV 文件在我们要搜索的列之前和之后有大约 15 列。此外,一些列值有逗号,所以我不能真正依赖-Delimiter ,。此外,某些列值没有 "(如果您要以 txt 格式打开 CSV)。

【问题讨论】:

    标签: csv powershell powershell-3.0


    【解决方案1】:

    如果值被正确引用(即如果 CSV 有效),则包含逗号的列不应该成为问题。 Import-Csv 将正确地将记录 42,"a,b",c 导入为三个值 42a,bc。如果您的 CSV 格式不正确:请先修复它。

    从第一个 CSV 文件中获取登录 ID:

    $logins = Import-Csv 'C:\path\to\file1.csv' |
              Where-Object { $_.Type -eq 'H' -and $_.ContractorDomain } |
              Select-Object -Expand LoginNumber
    

    您可以将ContractorDomain 属性检查简化为仅$_.ContractorDomain,因为在该上下文中,PowerShell 会同时解释空字符串和$null as a boolean value $false。其他零值或空值(0、0.0、空数组等)也会发生同样的情况,但这在您的场景中应该不是问题。

    接下来创建一个hashtable 将帐户名称映射到它们各自的状态。按您之前创建的 ID 列表过滤导入的第二个 CSV,因此哈希表仅包含相关映射。

    $accountStatus = @{}
    Import-Csv 'C:\path\to\file2.csv' | Where-Object {
      $logins -contains $_.UserIDNumber
    } | ForEach-Object {
      $accountStatus[$_.SamAccountName] = $_.AccountStatus
    }
    

    使用该哈希表,您现在可以将 UserStatus 列添加到您的第三个 CSV:

    (Import-Csv 'C:\path\to\file3.csv') |
      Select-Object -Property *, @{n='UserStatus';e={
        if ($accountStatus.ContainsKey($_.SameAccountName)) {
          $accountStatus[$_.SameAccountName]
        } else {
          'User Match Not Found'
        }
      }} | Export-Csv 'C:\path\to\file3.csv' -NoType
    

    Import-Csv 语句周围的括号确保文件在Export-Csv 开始写入之前已被完全读取并关闭。仅当您将修改后的数据写回同一文件时才需要它们,否则可以省略。星号选择所有导入的列,附加的calculated property 添加您要包含的新列。

    【讨论】:

    • 这看起来很不错。我已经为之前的代码工作了 2 天,所以我第一次有机会测试它(可能在几个小时的睡眠之后),如果它通过了,我会标记你的答案。非常感谢:)
    • 经过测试,效果很好!对不起,我花了这么长时间才回复。为了达到这一点,我不得不重做我有 1 天时间编写的 QuickAndDirty 代码。我最终只是将信息从file2附加到file3,所以现在搜索只需要在file1和file3之间进行。原因是有 18 种不同类型的 file2,无需搜索 18 个文件。所以我不得不稍微修改一下代码,但你解释得很好。非常感谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 2014-12-17
    • 2018-12-14
    • 1970-01-01
    • 1970-01-01
    • 2012-05-31
    相关资源
    最近更新 更多