在Powershell中延迟执行管道?

时间:2019-12-29 07:27:45

标签: powershell pipeline

是否可以延迟管道执行或修改先前的管道?我正在寻找的是与ODATA端点进行交互的能力。我想使用标准(或自定义)powershell命令来过滤数据,但是我不想检索整个列表。例如

function Get-Records() {
    Invoke-RestMethod -Method Get -Uri $endpoint.Uri.AbsoluteUri ...
}

调用此方法可以返回500多个记录。通常,有时我不想检索所有500条记录。因此,如果我需要全部500个,我可能会打电话给Get-Records。但是,如果我只想要特定的电话,我会想做的

Get-Records | Where {$_.Name -eq 'me'}

以上内容仍接收所有500条记录,然后将其过滤。我想以某种方式希望Where {$_.Name -eq 'me'}传递回上一个管道,将过滤器传递到Invoke-RestMethod并附加到URI $filter=Name eq 'me'

1 个答案:

答案 0 :(得分:1)

您不能通过Where-Object之类的后处理过滤器来追溯修改管道。

相反,您必须使用数据提供者的语法在源位置过滤

PowerShell内置的cmdlet(例如Get-ChildItem)是通过[string]类型的-Filter 参数来实现的。

如果要传递PowerShell 脚本块作为过滤器,则必须自己将其转换为提供程序的语法-

很少有PowerShell表达式与提供程序的过滤器功能的一对一映射,因此也许更好的方法是要求用户直接使用提供程序的语法

function Get-Records() {
  param(
   [Parameter(Mandatory)]
   [uri] $Uri
   ,
   [string] $Filter # Optional filter in provider syntax; e.g. "Name eq 'me'"
  )
    if ($Filter) { $Uri += '?$filter=' + $Filter }
    Invoke-RestMethod -Method Get -Uri $uri
}

# Invoke with a filter in the provider's syntax.
Get-Records "Name eq 'me'"

如果您希望用户能够传递脚本块,则必须对提供程序语法进行自己的翻译,并确保可以进行翻译。

要稳健地执行此操作,您必须处理脚本块的AST(抽象语法树),可以通过其.Ast属性来访问它,这是不平凡的。

如果您愿意对允许用户传递的表达式类型做出假设,则可以通过 string解析摆脱困境,例如下面的简单示例:


function Get-Records {
  param(
   [Parameter(Mandatory)]
   [uri] $Uri
   ,
   [scriptblock] $FilterScriptBlock # Optional filter
  )
    if ($FilterScriptBlock) { 
      # Translate the script block' *string representation*
      # into the provider-native filter syntax.
      # Note: This is overly simplistic in that it simply removes '$_.'
      #       and '-' before '-eq'.
      $Uri += '?$filter=' + $FilterScriptBlock -replace '\$_\.' -replace '-(?=[a-z]+\b)'
    }
    Invoke-RestMethod -Method Get -Uri $Uri
}

# Invoke with a filter specified as a PowerShell script block.
Get-Records { $_.Name -eq 'me' }