powershell 有关管道变量和管道快捷方式的问题?

oxcyiej7  于 2023-01-05  发布在  Shell
关注(0)|答案(1)|浏览(133)

在我正在编写的脚本的创建过程中,我偶然发现使用了一种我从未见过的管道快捷方式。
例如:

$acl | select -expandproperty Access | ? {$_.IdentityReference -eq "AD\$Group"}

     can be shortened to

$acl.Access.Where({$_.IdentityReference -eq "AD\$Group"})

这是什么?$acl。Access对我来说是有意义的,因为它只是一个属性引用,但我没有看到任何这样的。Where()方法在此对象上可用。看起来是这样。Where({})是某种管道快捷方式,用于"| Where-Object {}"。我在哪里可以找到这样的文档?是否存在其他类似的文档?

    • 第二个问题**.我需要向结果中添加一个计算属性,并且在属性表达式中还必须执行管道操作,因此,通常我只从父管道引用$_,但在表达式语句中会丢失。

我可以通过在管道中使用-PipelineVariable来解决这个问题,但似乎只有在与cmdlet一起使用时才有效,而在使用变量启动管道时(我经常这样做),这个问题无法解决。
这是可行的:

$acl = Get-Acl -Path "AD:\$dn"
$acl | select -expandproperty access -PipelineVariable AccessRight | ? {$_.IdentityReference -eq "AD\$Group"} | select *, @{N='ObjectTypeName';E={($ADGuidMap.GetEnumerator() | ? {$_.Value -eq $AccessRight.ObjectType}).Name}}

我真的希望能够做到这一点的捷径,因为任何地方我可以缩短我的oneliner我想这样做。不幸的是,以下将无法工作,因为我不能使用pipelinevariable在这个位置。

$acl.Access.Where({$_.IdentityReference -eq "AD\$Group"}) -PipeLineVariable AccessRight | select *, @{N='ObjectTypeName';E={($ADGuidMap.GetEnumerator() | ? {$_.Value -eq $AccessRight.ObjectType}).Name}}

它总是困扰着我不能在cmdlet之外使用管道变量,所以我最终想问一下是否有某种方法可以解决这个问题。

bwitn5fc

bwitn5fc1#

关于第一个问题:

  • .Where().ForEach() * 方法 * 是intrinsic members,即PowerShell隐式提供的可用于 * any * 类型对象的成员。
  • 虽然它们的功能与对应的 * cmdlet * Where-ObjectForEach-Object * 类似 *,但也有重要的区别。
  • 有关详细信息,请参见this answer

顺便说一句:即使在使用Where-Object cmdlet(即simplified syntax)时,您也可以简化命令:

$acl.Access | Where-Object IdentityReference -eq "AD\$Group"

关于第二个问题:
因为.Where() * 方法 * 不是 * cmdlet *,所以不能使用公共
-PipelineVariable参数。
考虑到.Access通常返回 * 多个 * 对象,使用-PipelineVariable的管道可以实现一个优雅的解决方案。
如果您确实希望避免管道(运算符),则可以在中间(常规)变量的帮助下组合.Where().ForEach()方法,如下所示:

$acl.Access.
  Where({ $_.IdentityReference -eq "AD\$Group" }).
  ForEach({
      $aclEntry = $_
      Select-Object -InputObject $aclEntry -Property *, 
        @{
          N = 'ObjectTypeName'
          E = { ($ADGuidMap.GetEnumerator().Where({ $_.Value -eq $aclEntry.ObjectType })).Name }
        }
    })

更新:
正如您所发现的,如果您坚持使用管道,可以将-PipeLineVariableWrite-Output结合使用,以便在数组/集合的每个元素流经管道时将其捕获到管道变量中,以供后面的脚本块使用,如以下(人为设计的)示例所示:

$array = 0..3
Write-Output $array -Pipeline arrayElement |
Where-Object { 0 -eq $_ % 2 } | # filter out odd numbers
 ForEach-Object { $_ + 1 } | # add 1
 ForEach-Object { "pipeline variable / `$_: $arrayElement / $_" }

输出,显示输入数组$array的每个元素都在管道变量$arrayElement中单独捕获:

pipeline variable / $_: 0 / 1
pipeline variable / $_: 2 / 3

相关问题