通过管道传递多个值

Posted

技术标签:

【中文标题】通过管道传递多个值【英文标题】:Pass multiple values through pipeline 【发布时间】:2019-03-27 04:24:37 【问题描述】:

我希望能够通过管道为我正在构建的模块传递多个值。该模块是围绕特定的 SQL 数据库架构构建的,因此我设计了这个函数来返回该架构的所有数据库:

function Get-TRISDatabases 
    param (
        [parameter(mandatory=$false)]
        [string]$ServerAddress = "localhost",
        [parameter(mandatory=$false)]
        [switch]$Name
    )
    Begin 
        $Query_GetDatabases = "
            SELECT Name, create_date, user_access_desc, state_desc, recovery_model_desc FROM   sys.databases WHERE  CASE
                WHEN state_desc = 'ONLINE' THEN OBJECT_ID(QUOTENAME(name) + '.[dbo].[CRISFiles]', 'U')
            END IS NOT NULL
        "
    

    Process 
        ## Get Data
        $rValue = Invoke-Sqlcmd2 -Query $Query_GetDatabases -ServerInstance $ServerAddress

        ## Return values
        if ($Name) 
            Return $rValue.Name
        
        else 
            Return $rValue
        
    

    End 
        ## Purge Variables
        Remove-Variable Query_GetDatabases, rValue
    

这很好用,但我想要的是能够通过管道传递 $serverAddress 和 $rValue 变量。这样我就可以像这样运行其他命令:

Get-TRISDatabases -name -ServerAddress "server1" | Remove-TRISDeadLinks

而不是我现在拥有的:

Get-TRISDatabases -name -ServerAddress "server1" | Remove-TRISDeadLinks -ServerAddress "server1"

我也尝试将服务器地址放在 rValue 对象中,但我必须更改所有其他脚本以使用服务器地址 rValue.ServerAddress 才能工作。

删除-TRISDeadLinks 参数块:

param (
    [parameter(
        Mandatory=$false, Position=1,ValueFromPipeline=$false
    )]
    $ServerAddress = "localhost",

    [parameter(
        Mandatory=$false, Position=2,ValueFromPipeline=$true
    )]
    $Databases
)

-

.EXAMPLE
Remove-TRISBrokenLinks -ServerAddress "localhost" -Databases "Database1"

    Manually entering the server address and database

.EXAMPLE 
Remove-TRISBrokenLinks -ServerAddress "localhost" -Databases "Database1", "Database2"

    Runs against an array of databases names

.EXAMPLE 
Get-TRISDatabases -ServerAddress "Localhost" -name | Remove-TRISBrokenLinks

    Uses the Get-TRISDatabases function to pass all TRIS databases to the function

【问题讨论】:

这归结为 remove-trisdatabases 的工作原理。如果它是您创建的函数,请执行help remove-trisdatabases,然后您可以将其设置为类似-serveraddress $_.name 的名称,其中名称是您在最后一个输出中调用的服务器名称属性。否则,您必须配置 param 块以接受管道输入。 remove-TRISDeadLinks 参数块接受数据库作为管道输入,而不是服务器地址。我想要两者,但我也希望能够在没有管道输入的情况下手动运行它(见编辑) 【参考方案1】:

一般来说,process 脚本块允许像任何其他脚本块一样输出多个对象;例如:

PS> 'one', 'two' | &  param([Parameter(ValueFromPipeline)] $str) process  $str; 'hi'   
one
hi
two
hi

请记住,return <object> 只是用于输出 <object> 和从脚本块返回的语法糖,您不需要 return输出一个对象。


但是,鉴于您的特定要求 - 将另一个函数的 两个 参数与您的函数的输出通过管道 绑定 - 您需要:

使Get-TRISDatabases 输出一个自定义对象,其属性是要传递给两个参数的参数。

定义您的其他函数以绑定管道中的这些属性按属性名称

# Get-TRISDatabases ...

Process 
    ## Get Data
    $rValue = Invoke-Sqlcmd2 -Query $Query_GetDatabases -ServerInstance $ServerAddress

    # Output a custom object with both $rValue and the server address
    [pscustomobject] @
      ServerAddress = $ServerAddress
      Databases = if ($Name)  $rValue.Name  else  $rValue 
    



# ...

然后定义你的Remove-TRISDeadLinksparam()块如下(PSv3+;注意参数默认是非强制性的,它们的位置是由它们的声明顺序暗示的):

# Remove-TRISDeadLinks ...
[CmdletBinding()]
param (
    [Parameter(ValueFromPipelineByPropertyName)]
    $ServerAddress = "localhost"
    ,   
    [Parameter(ValueFromPipelineByPropertyName)]
    $Databases
)

【讨论】:

我的荣幸,@OwainEsau;很高兴听到它有帮助。

以上是关于通过管道传递多个值的主要内容,如果未能解决你的问题,请参考以下文章

通过管道从多个子进程写入父进程

Linux 利用管道父子进程间传递数据

通过js页面重定向代码传递多个值

通过 Razor 页面传递多个参数值

[Go] 通过 17 个简短代码片段,切底弄懂 channel 基础

通过 http 管道将逗号分隔的值转换为 list<string>