【问题标题】:Select-Object -Unique选择对象-唯一
【发布时间】:2021-03-03 18:31:25
【问题描述】:

我的理解是这样的

$list = @('1', '2', '3', '1', '4')
Select-Object -InputObject $list -Unique

应该返回一个只有 4 个元素的数组,跳过第二个不唯一的“1”。

但我正在恢复所有 5 个元素。我是否理解错了,或者 Select-Object 是否有错误,至少在我正在测试的 PS 5.1 中?

【问题讨论】:

  • '1', '2', '3', '1', '4'|Select-Object -Unique 按预期工作。不知何故,使用 -InputObject 会出错。有趣...
  • 在文档中找到:-InputObject 指定要通过管道发送到 cmdlet 的对象。此参数使您能够将对象通过管道传输到 Select-Object。当您将对象传递给 InputObject 参数时,Select-Object 不使用管道,而是将 InputObject 视为单个对象,即使该值是一个集合。建议您在将集合传递给 Select-Object 时使用管道。
  • @gert-jan-kraaijeveld 很好的发现!还有一个有趣的问题,因为我通常尽可能避免使用管道,因为 1:管道污染是一个问题,2:管道很慢。

标签: powershell parameter-passing pipeline


【解决方案1】:
  • 只有少数例外,特别是 ConvertFrom-CsvGet-RandomJoin-StringGet-Member-InputObject 参数应被视为 实现细节,其目的是促进管道输入,因此不应直接使用。内置 cmdlet 属于以下类别之一:

    • A 类:少数几个 cmdlet,例如 Get-Member 有用 区分将输入集合作为 参数 传递给 -InputObject并通过管道隐式枚举集合的元素

    • B 类:选择几个 cmdlet,例如 ConvertFrom-Csv(但不是 ConvertTo-Csv)、Get-RandomJoin-StringOut-String,要么有 array-valued -InputObject 参数(例如 -InputObject <psobject[]>),要么显式执行枚举 对传递给它们的标量 InputObject 的参数参数(例如,-InputObject <psobject>)。

      • 对于 flat 输入集合(典型)[1],此类 cmdlet 有效地将直接参数传递视为管道输入 - 除了直接参数传递快得多;见下文。
    • C 类:不幸的是,大多数 cmdlet 都有标量 -InputObject 参数进程集合传递给 -InputObject作为一个整体,这有效地使参数对于直接参数传递无用

  • 有点不幸,因为将已经在内存中的集合作为参数传递给 cmdlet 比逐个发送其元素要快得多管道

    • 例如,比较使用直接参数传递或管道传递 100 万个项目与 Get-Random 的运行时间:Get-Random -InputObject (1..1e6) vs.
      1..1e6 | Get-Random

    • 请注意,此优化有时也可用于其他 cmdlet 参数;值得注意的是,您可以将集合传递给Set-Content-Value 参数作为管道的替代方法,这大大加快了编写速度。


这是一个按字母顺序分类的内置 cmdlet 列表:

  • A 类:管道输入和显式-InputObject 之间的有用区别使用:作为一个整体处理集合,将它们传递给-InputObject;要一一处理它们的元素,请使用管道:

    • Add-Member
    • Export-Clixml
    • Get-Member
    • Trace-Command
  • B 类:flat 集合的有用等效项:您可以将平面集合直接传递给 -InputObject 以加快处理速度:

    • ConvertFrom-Csv
    • Format-Custom
    • Format-List
    • Format-Table
    • Format-Wide
    • Get-Random
    • Join-String
    • Out-Host
    • Out-String
  • C 类:无用的区别:直接-InputObject 使用毫无意义:

    • ConvertTo-Csv
    • ConvertTo-Html
    • ConvertTo-Xml
    • Export-Csv
    • ForEach-Object
    • Format-Hex
    • Get-Unique
    • Group-Object
    • Invoke-Command
    • Measure-Command
    • Measure-Object
    • Select-Object
    • Select-String
    • Sort-Object
    • Start-Job
    • Update-List
    • Where-Object

[1]管道输入和-InputObject使用之间嵌套集合的处理差异:

那些枚举其-InputObject 参数的cmdlet 仅对输入集合执行一个 级别的枚举,并保持嵌套 集合原样。

相比之下,使用管道会导致 级迭代,如以下 Join-String 示例所示:

PS> Join-String -InputObject ('foo', ('bar', 'baz'))
foobar baz

foo 和嵌套数组的字符串化作为一个整体 - bar baz - 被加入。

PS> 'foo', ('bar', 'baz') | Join-String
foobarbaz

foo 和嵌套数组的枚举元素 已连接。

原因是由于管道的枚举行为,在这种情况下发生了两次处理:首先传递foo,然后是嵌套数组'bar', 'baz',然后是单级枚举在每个上执行,所有输入对象的结果都被连接起来。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    相关资源
    最近更新 更多