【问题标题】:powershell filter csvpowershell过滤器csv
【发布时间】:2013-04-08 08:53:42
【问题描述】:

由于我是 Powershell 新手,因此寻求最佳实践方面的帮助,

我有一个 csv 文件,我想过滤掉 csv 中的每一行,除了包含“未安装”的行

然后,我想根据包含计算机列表的单独 csv 文件过滤这些结果,并排除任何包含匹配项的行。

任何帮助或起点将不胜感激!

【问题讨论】:

    标签: powershell csv


    【解决方案1】:

    对于第一部分,您可以使用Select-String -Notmatch ... 例如:

    $file = "data.csv"
    $csv = Get-Content $file
    $csv | Select-String -Notmatch 'Not Installed' | Out-File $file -Enc ascii
    

    如果您的 CSV 文件恰好是 Unicode,则删除“-Enc ascii”部分,因为 Out-File 的默认值是 Unicode。至于你问题的第二部分,你需要更具体一些。但是,您应该查看有关 Import-Csv 和 Export-Csv 的帮助:

    man Import-Csv -full
    man Export-Csv -full
    

    【讨论】:

    • 这实际上效果很好。我以前有类似的命令,但没有指定 -Enc ascii 所以它给我带来了不受欢迎的结果。第二部分需要将新的 data.csv 文件与另一个包含需要过滤掉的排除项的 csv 列表进行比较。上面的命令可能会起作用,也许我可以将排除列表的内容获取到一个数组中并将“未安装”更改为 $exclusions?
    • 如果你使用 Import-Csv 来拉入两个 CSV 文件,你会得到一个对象数组,其中每个对象都有与 CSV 文件中的字段对应的属性。所以你可以做这样的事情$importedCsv1 | Where {$csv1Field= $_.Field; ($importedCsv2 | Where {$_.FilterField -eq $csv1Field}).Count -eq 0 }
    • $csv |选择字符串-NotMatch $exclusions | Out-File $hosts -Enc ascii 用于从 data.csv 文件中删除所有排除项,但它会在其删除的每个匹配项的顶部留下一个空白行。有什么想法吗?
    • 看起来像 MatchInfo 对象的 PS 格式。试试这个$csv | Select-String -NotMatch $exclusions | Foreach {$_.Line} | Out-File $hosts -enc ascii
    • 这是我完成的脚本:#将所有 csv 文件复制到一个文件中 (Get-Content *.csv) | Set-Content hosts.csv $exclusions = Get-Content "c:\Sandbox\TMVS\exclusions.csv" $hosts = "hosts.csv" $csv = Get-Content $hosts #过滤 csv 仅适用于未安装任何计算机的计算机 $ CSV | Select-String -pattern '未安装' | Out-File $hosts -Enc ascii #Filters hosts list 以删除排除列表中列出的所有客户端 ($csv = Get-Content $hosts) |选择字符串-NotMatch $exclusions |输出文件 $hosts -Enc ascii
    【解决方案2】:

    get-help *csv*

    get-help import-csv -examples

    名为 test.txt 的示例 csv 文件

    header1,header2,header3
    installed,2,3
    not installed,2,3
    

    将文件导入powershell变量并过滤。

    $p = Import-CSV .\test.txt
    $p | Where { $_.header1 -eq 'installed'}
    

    【讨论】:

      【解决方案3】:

      在尝试自己解决如何做同样的事情时遇到了这个问题。

      我想出的解决方案如下:

      $Filtered = $Table|Select-String -Pattern $ExcludeStrings -NotMatch -SimpleMatch
      $FilteredArray = @()
      $Filtered.Line | foreach {$split = $_ -split ';';
                                $tidied = $split -replace '@|{|}|^ ';
                                $obj = New-Object System.Object
                                $tidied|foreach {$obj|Add-Member -MemberType NoteProperty -Name ($_.split('=')[0]) -Value ($_.split('=')[1])
                                                  }
                                $FilteredArray += $obj  
                                  }
      

      第一行只是显示我过滤了我通过Import-CSV 获得的数组以仅获得我想要的结果。

      不幸的是,这给我留下了一个 MatchInfo 数组,每个数组的格式如下:

      @{Column1=Value1; Column2=Value2; Column3=Value3;}
      

      这根本不能很好地导出回 CSV。

      所以,我选择创建一个新的输出数组 ($FilteredArray)。

      然后,我将 matchinfo 数组的 Line 属性从 Select-String 传送到 foreach 循环中,对于每一行,我将其拆分为分号,然后删除 @{} 字符和任何前导空格.

      然后我创建一个新的System.Object,然后将整理后的输出通过管道传输到另一个 foreach 循环中,在 obj 中创建新的 NotePropertys,将它们从整理后的输出中的当前行命名为 = 字符,值为= 字符后的剩余文本。

      我最终得到的是:

      PS C:\Users\Graham> $obj
      
      Column1            : Value1
      Column2            : Value2
      Column3            : Value3
      

      过滤后的数组看起来像:

      PS C:\Users\Graham> $FilteredArray[0..3]|Format-table
      
      Column1         Column2        Column2                                    
      -------         -------        -------
      Value1          Value2         Value3 
      Value1          Value2         Value3
      Value1          Value2         Value3
      

      【讨论】:

      • @paul-rowland 给出的解决方案在使用-notmatch 过滤器时会以更简单的方式实现此结果。找出要排除(或匹配)的文本列 - 在我的示例中,“OSName”是包含操作系统名称的列,我想排除服务器操作系统。要生成带有条目的过滤表作为 PSCustomObjects 准备进一步处理,请导入 CSV,然后执行$filtered = $csv | where { $_.OSName -notmatch 'Server'} 之类的操作
      猜你喜欢
      • 2022-01-09
      • 2021-12-06
      • 1970-01-01
      • 2018-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多