Powershell 选择对象-唯一

Powershell 选择对象-唯一,powershell,parameter-passing,pipeline,Powershell,Parameter Passing,Pipeline,我的理解是 $list = @('1', '2', '3', '1', '4') Select-Object -InputObject $list -Unique 应返回仅包含4个元素的数组,跳过第二个非唯一的“1” 但我正在找回所有5个元素。我是否理解错了,或者Select对象是否至少在我测试的PS 5.1中有缺陷? 除了少数例外,从Csv转换,获取随机,连接字符串,以及获取成员,应将-InputObject参数视为实现细节,其目的是方便管道输入,因此,不应直接使用。内置cmdlet可分为以

我的理解是

$list = @('1', '2', '3', '1', '4')
Select-Object -InputObject $list -Unique
应返回仅包含4个元素的数组,跳过第二个非唯一的“1”

但我正在找回所有5个元素。我是否理解错了,或者Select对象是否至少在我测试的PS 5.1中有缺陷?

  • 除了少数例外
    从Csv转换
    获取随机
    连接字符串
    ,以及
    获取成员
    应将
    -InputObject
    参数视为实现细节,其目的是方便管道输入
    ,因此,不应直接使用。内置cmdlet可分为以下类别之一:

    • 类别A:选择一些cmdlet(如
      Get Member
      )可以有效区分将输入集合作为参数传递给
      -InputObject
      和通过管道隐式枚举集合的元素

    • 类别B:选择一些cmdlet,例如
      ConvertFrom Csv
      (但不是
      ConvertTo Csv
      )、
      Get Random
      Join String
      Out String
      ,它们都具有数组值
      -InputObject
      参数(例如
      -InputObject
      )或者显式地对传递给其标量
      InputObject
      参数的参数执行枚举(例如,
      -InputObject

      • 对于平面输入集合(这是典型的)[1],这种cmdlet有效地处理直接参数传递与管道输入相同——只是直接参数传递快得多;见下文
    • 类别C:不幸的是,大多数cmdlet都将标量
      -InputObject
      参数和进程集合作为一个整体传递给
      -InputObject
      ,这实际上使参数对于直接参数传递毫无用处

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

    • 例如,使用直接参数传递或管道:
      Get Random-InputObject(1..1e6)

      比较将100万项传递给
      Get Random
      的运行时
      1..1e6 |随机获取

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


以下是按字母顺序分类的内置cmdlet列表:

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

    • 添加成员
    • 导出Clixml
    • Get Member
    • 跟踪命令
  • 类别B:平面集合的有用等效性:您可以将平面集合直接传递给
    -InputObject
    ,以加快处理速度:

    • convertfromcsv
    • 自定义格式
    • 格式列表
    • 格式表
    • 格式范围
    • 随机获取
    • 连接字符串
    • Out主机
    • 输出字符串
  • C类:无用的区别:直接
    -InputObject
    使用是无意义的:

    • 转换为Csv
    • 转换为Html
    • 转换为Xml
    • 导出Csv
    • ForEach对象
    • 十六进制格式
    • Get Unique
    • 组对象
    • Invoke命令
    • 测量命令
    • 测量对象
    • 选择对象
    • 选择字符串
    • 排序对象
    • 开始作业
    • 更新列表
    • Where对象

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

枚举其
-InputObject
参数的cmdlet仅对输入集合执行一级枚举,并保持嵌套集合不变

相比之下,管道的使用会导致两级迭代,如下例所示:

PS> Join-String -InputObject ('foo', ('bar', 'baz'))
foobar baz
foo
和嵌套数组作为一个整体的字符串化——
bar baz
——结合在一起

PS> 'foo', ('bar', 'baz') | Join-String
foobarbaz
foo
和嵌套数组的枚举元素已联接

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

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

'1',2',3',1',“4”|选择对象-唯一性
可按预期工作。不知何故,使用-InputObject会使它出错。有趣的…在文档中可以找到:-InputObject指定要通过管道发送到cmdlet的对象。通过此参数,可以通过管道对象选择对象。将对象传递给InputObject参数时,即使值是集合,选择对象也会将InputObject视为单个对象,而不是使用管道。建议在传递集合以选择对象时使用管道。@gert jan-
PS> 'foo', ('bar', 'baz') | Join-String
foobarbaz