使用PowerShell比较两个不同的csv文件

时间:2019-11-14 05:46:36

标签: powershell compare export-to-csv

我正在寻找一种比较2个.csv文件并比较结果的解决方案。

第一个.csv文件是基于客户端名称的每月备份大小,以KB为单位。第二个.csv文件是基于客户端名称的下一个每月备份大小(以KB为单位)。

它在A列中列出了所有客户端名称。B列具有相应的客户端策略名称,最后一列备份大小以KB为单位(即-487402463)。

如果客户端大小之间的差异(1638838488-1238838488 = 0.37 in TB)大于0.10 TB,则结果将以TB大小吐出到csv文件中,如下所示。

此外,客户端可能与多个策略名称相关。

我的问题是:我也想添加一些内容。有时,它可能是重复的客户端和策略名称,例如主机名XX,Company_Policy_XXX或区分大小写的HOSTNAMEXX,Company_Policy_XXX。 此外,假设,如果CSV2中不存在主机名YY,Company_Policy_XXX,41806794,那么我想显示为负数,如下所示。

我使用了Join-Object模块。

示例CSVFile1.csv

Client Name,Policy Name,KB Size
hostname1,Company_Policy,487402463
hostname2,Company_Policy,227850336
hostname3,Company_Policy_11,8360960
hostname4,Company_Policy_11,1238838488
hostname1,Company_Policy_55,521423110
hostname10,Company_Policy,28508975
hostname3,Company_Policy_66,295925
hostname5,Company_Policy_22,82001824
hostname2,Company_Policy_33,26176885
hostnameXX,Company_Policy_XXX,0
hostnameXX,Company_Policy_XXX,41806794
hostnameYY,Company_Policy_XXX,41806794

示例CSVFile2.csv

Client Name,Policy Name,KB Size
hostname1,Company_Policy,487402555
hostname2,Company_Policy,227850666
hostname3,Company_Policy_11,8361200
hostname4,Company_Policy_11,1638838488
hostname1,Company_Policy_55,621423110
hostname10,Company_Policy,28908975
hostname3,Company_Policy_66,295928
hostname5,Company_Policy_22,92001824
hostname2,Company_Policy_33,36176885
hostname22,Company_Policy,291768854
hostname23,Company_Policy,291768854

所需的输出:

Client Name,Policy Name,TB Size
hostname4,Company_Policy_11,0.37
hostname22,Company_Policy,0.27
hostname23,Company_Policy,0.27
hostnameYY,Company_Policy_XXX,-0.03
hostnameXX,Company_Policy_XXX,-0.04

2 个答案:

答案 0 :(得分:1)

使用此Join-Object cmdlet(另请参见:what's the best way to join two tables into one?):

$CSV2 | FullJoin $CSV1 `
    -On 'Client Name','Policy Name' `
    -Property 'Client Name',
              'Policy Name', 
              @{'TB Size' = {[math]::Round(($Left.'KB Size' - $Right.'KB Size') * 1KB / 1TB, 2)}} | 
    Where-Object  {[math]::Abs($_.'TB Size') -gt 0.01}

结果:

Client Name Policy Name        TB Size
----------- -----------        -------
hostname4   Company_Policy_11    -0.37
hostname1   Company_Policy_55    -0.09
hostnameXX  Company_Policy_XXX    0.04
hostnameYY  Company_Policy_XXX    0.04
hostname22  Company_Policy       -0.27
hostname23  Company_Policy       -0.27

更新2019-11-24

改进的-Where参数现在也适用于外部联接。
现在,对于这些类型的查询,您可以使用-Where参数而不是Where-Object cmdlet,例如:

$Actual = $CSV2 | FullJoin $CSV1 `
    -On 'Client Name','Policy Name' `
    -Property 'Client Name',
              'Policy Name', 
              @{'TB Size' = {[math]::Round(($Left.'KB Size' - $Right.'KB Size') / 1GB, 2)}} `
    -Where {[math]::Abs($Left.'KB Size' - $Right.'KB Size') -gt 100MB}

使用-Where参数的优点是性能有所提高,因为根本不需要创建某些输出对象。

注释1 -Where参数适用于分别代表$Left和{{的$Right$LeftInput对象1}}对象,而不是输出对象。换句话说,您不能使用此示例在$RightInput表达式中计算出的TB Size属性。

注释2 -Where对象始终存在于左联接或完全联接中,即使没有关系也是如此。如果没有关系,则$Right对象的所有属性都将设置为$Right。右键连接或完全连接中的$Null对象也是如此。

答案 1 :(得分:-1)

我从未使用过Join-Object模块,所以我使用标准cmdlet编写了它。

$data1 = Import-Csv "CSVFile1.csv"
$data1 | ForEach-Object { $_."KB Size" = -1 * $_."KB Size" } # Convert to negative value

$data2 = Import-Csv "CSVFile2.csv"

@($data2; $data1) | Group-Object "Client Name","Policy Name" | ForEach-Object {
    $size = [Math]::Round(($_.Group | Measure-Object "KB Size" -Sum).Sum * 1KB / 1TB, 2)
    if ($size -ge 0 -and $size -lt 0.1) { return }
    [pscustomobject]@{
        "Client Name" = $_.Group[0]."Client Name"
        "Policy Name" = $_.Group[0]."Policy Name"
        "TB Size" = $size
    }
}