【问题标题】:Compare PSCustomObject to Object将 PSCustomObject 与 Object 进行比较
【发布时间】:2019-04-15 13:38:17
【问题描述】:

我创建了一个PsCustomObject,当调用变量是ISE时,它会读取一个相关数据的表。但是,如果我尝试将PsCustomObject 与另一个对象进行比较,PsCustomObject 将无法正确读取。如果现有 CSV 中的任何行与 PSCustomObject 匹配,我想告诉脚本不要将数据导出到 CSV,换句话说,跳过 CSV 文件中的重复行。 CSV 可能有也可能没有多行。

$fileInfo = @(
                        [pscustomobject]@{
                            user_id = $user
                            studio = $studio
                            function = $Task
                            end_time_local = $creationTime
                            asin = $ASIN
                            variant = $variant
                            process_class_id = $processClass
                            }
                           )
$currentData = Import-Csv "$scansFolder\$fileName.csv"
if($fileInfo -ne $currentData){
$fileInfo | Export-Csv "$scansFolder\$fileName.csv" -Append -NoTypeInformation -Force
}

【问题讨论】:

  • 导入的CSV是什么结构?如果它们相同,则使用Compare-Object cmdlet。
  • 您的$fileInfo 变量是一个数组。您是否需要支持 多个 自定义对象从 CSV 中排除?
  • @Lee_Dailey csv和自定义对象一样,有headers和$fileInfo中提到的7项。
  • @mklement0 我认为这可能是问题所在,我尝试了以下类似的方法,但没有成功。 foreach($line in $currentData){ if($fileInfo -ne $currentData){ $fileInfo | Export-Csv "$scansFolder\$fileName.csv" -Append -NoTypeInformation -Force }}关于如何做到这一点的任何想法?
  • @Garrett - 您可以使用Compare-Object cmdlet 来确定一个对象是否在类似对象的集合中。看看-IncludeEqual 参数。

标签: powershell pscustomobject


【解决方案1】:

[pscustomobject] 是 .NET reference 类型,因此比较两个实例[1]-eq 将测试 reference 相等性 (身份),即如果两个实例是同一个对象[2] - 这显然不是你的场景。

假设您的自定义对象的 propertiesvalue typesstrings 的实例(似乎是这种情况),您可以使用Compare-Object 按对象的属性值比较对象,并能够比较两个集合

$fileInfo = @(
  [pscustomobject]@{
      user_id = $user
      studio = $studio
      function = $Task
      end_time_local = $creationTime
      asin = $ASIN
      variant = $variant
      process_class_id = $processClass
      }
)

# Get the property names.
# This assumes that the CSV data has (at least) the same
# set of properties (columns).
$propNames = $fileInfo[0].psobject.properties.Name

$currentData = Import-Csv "$scansFolder\$fileName.csv"

# Compare the $fileInfo custom object(s) to the custom objects read
# from the CSV file and only export those that are unique to the RHS ('=>')
# back to the file, i.e., those that don't match $fileInfo.
Compare-Object -Property $propNames $fileInfo $currentData |
  Where-Object SideIndicator -eq '=>' | Select-Object InputObject | 
    Export-Csv "$scansFolder\$fileName.csv" -Append -NoTypeInformation -Force

[1] Import-Csv 也输出 [pscustomobject] 实例。

[2] 请参阅 Equality Comparison 帮助主题(为 C# 编写,但类似地适用于 PowerShell 的 -eq 运算符)。

【讨论】:

  • @Garrett:所以属性名称匹配。我不清楚您打算如何检查重复项:您的问题使用 [pscustomobject] 文字与 CSV 数据进行比较,这就是我的回答向您展示的方法。您是说$fileInfo 来自一个不同的 文件吗?或者您是否需要清除给定文件中的重复项?您如何确定新功能?
  • @Garrett,我仍然不确定我是否完全理解,但您可以通过单个 Import-Csv 调用将多个 CSV 文件读入 $fileInfo,使用类似 Import-Csv -LiteralPath (Get-Item *.csv) 的东西(使用 string *.csv 可能不起作用,由于这个this bug),并将其与通过Compare-Object 读入$currentData 的参考CSV 文件中的对象进行比较,如图所示。
  • @Garrett,您最好持续跟踪您已经处理过的文件,尤其是随着文件数量的增加以及输出 CSV文件增长。除此之外,我在之前的评论中推荐的应该可行:将所有输入 CSV 文件读入$fileInfo - $fileInfo = Import-Csv -LiteralPath (Get-Item c:\path\to\inputs\*.csv) - 然后使用Compare-Object 调用$currentData,如答案所示。
  • 一般来说,我建议我们结束这个问题:我的回答解决了你的问题as ask,所以我建议你接受它;如果有后续问题,请创建一个问题(完成后请随时在此处联系我)。
  • 基于上述建议,我用这个脚本走一条新路。我相信 mklement0 回答了最初的问题。
猜你喜欢
  • 2019-05-28
  • 1970-01-01
  • 2023-03-22
  • 2016-07-22
  • 1970-01-01
  • 2015-05-31
  • 2013-05-04
  • 2021-04-24
  • 2019-11-28
相关资源
最近更新 更多