我正在寻找一种比较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
答案 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
}
}