【问题标题】:Difference between using and not using pipe in Export-Csv in Powershell在 Powershell 的 Export-Csv 中使用和不使用管道的区别
【发布时间】:2017-09-29 22:51:45
【问题描述】:

这可能更像是一个“PowerShell 如何处理变量和管道”,而不是一个特定的编程问题,但由于(对我而言)这似乎是一种奇怪的行为,我想我会在这里发布它。

我只是在使用 PowerShell 将变量导出到 CSV 时遇到了一些困难,发现 this Stack question that helped me a lot。但是,在摆弄输出时,我得到了两个不同的结果,具体取决于我调用Export-CSV 函数的方式。

我有一个大致如下所示的自定义 PS 对象:

Account      Partner     ProjectName     ProjectPhase
1            A           Test            Start
2            B           Test2           Start
3            A           Test4           End
4            C           Test3           Middle
....

当我使用以下行时,它会正确输出 CSV 文件:

$csvBody | Export-Csv -Path "$targetPath\$fileName" -Encoding Unicode -NoTypeInformation

但是,当我使用以下行时,它不会:

Export-Csv -InputObject $csvBody -Path "$targetPath\$fileName" -Encoding Unicode -NoTypeInformation

在这种情况下,输出如下所示: 计数,"长度","LongLength","等级","SyncRoot","IsReadOnly","IsFixedSize","IsSynchronized" 263,"263","263","1","System.Object[]","False","True","False"

我从this other Stack post 了解到,输出成为 $csvBody 的属性,它是一个数组。我的问题是为什么当我没有将对象通过管道传输到 Export-CSV 时会发生这种情况,但是当我 am 使用管道时它不会发生

【问题讨论】:

  • 这是我尝试使用上述两种不同方法调用的同一个变量。输出要么成为变量的实际内容(使用管道时),要么成为数组的属性(不使用管道时)。我猜这与使用变量作为 -InputObject 或只是管道它之间的某种形式的差异有关,我的问题是这种差异是什么:)

标签: powershell csv


【解决方案1】:

我认为这是因为编写 Export-CSV 的目的是它应该(并且将)通常通过管道处理输入。

我认为您看到的行为是因为 -InputObject 参数不接受数组输入。您可以从帮助页面中看到:

   Export-Csv [[-Path] <String>] [[-Delimiter] <Char>] [-Append] [-Confirm] [-Encoding <String> {Unicode | UTF7 |
   UTF8 | ASCII | UTF32 | BigEndianUnicode | Default | OEM}] [-Force] -InputObject <PSObject> [-LiteralPath <String>]
   [-NoClobber] [-NoTypeInformation] [-WhatIf] [<CommonParameters>]

它是&lt;psobject&gt; 而不是&lt;psobject[]&gt;,因此它需要一个&lt;psobject&gt; 作为输入。当它通过参数行提供时,它似乎不会展开该对象,而是为您提供一个包含该对象本身的默认属性(长度等)的 CSV。

当您通过管道发送对象时,它使用 cmdlet PROCESS 接受管道输入的功能来展开对象并单独处理集合中的每个项目。

也许有人可以比我上面解释得更好,或者也许可以解释为什么 Export-CSV 不能按您期望的方式工作(除了 -- 我假设 -- 按设计)。

【讨论】:

  • 天哪,一定是这个。非常感谢您澄清这一点!我在这个问题上挠头太久了:)
【解决方案2】:

这里的一切都像设计一样写得不错

在第二种方式中,输入对象是#TYPE System.Object[],如果你保留TypeInformation,你可以看到。

当您使用管道调用 Export-Csv 时,集合的每个对象都被发送到 Cmdlet 的进程部分。


取整数集合:

$a = 1..4

然后尝试:

$a | Get-Member

它给出:System.Int32

那就试试吧:

Get-Member -InputObject $a

它给出:System.Object[]

所以在你的情况下,导出的对象是数组,它也很有用。

【讨论】:

  • 我是否正确地解释了 Mark Wragg 的解释,即 -InputObject 不接受数组,是这种行为的原因?
  • “写得不好”,让我有反应,因为首先,在五个版本之后,如果写得不好,它会被纠正,其次在 CmdLet 的语义中,你导出一个对象, object 是一个数组,你收到一个数组就可以了。当您将对象通过管道传输到 Cmdlet 时,您会收到对象。
  • 多个版本并不一定意味着会修复错误,但我同意你的观点,如果它被编写为采用单个对象(即,不是数组),那么它是设计使然,而不是“写得不好”。
  • 我将收回我的“写得不好”的评论,因为它不适合我。我确实认为 PowerShell 有时会做出一些错误的假设/默认设置,如果不破坏旧脚本的内容(例如 -notypeinformation 应该是 Export-CSV 的默认设置),则无法纠正这些假设/默认设置,但我认为我应该说的是(就像我在结束)这是/是设计使然。
猜你喜欢
  • 2016-12-10
  • 2016-07-01
  • 2019-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-29
  • 2021-01-16
相关资源
最近更新 更多