代码之家  ›  专栏  ›  技术社区  ›  Joey

如何编写接受管道输入的PowerShell脚本?

  •  73
  • Joey  · 技术社区  · 15 年前

    我正在尝试编写一个PowerShell脚本,该脚本可以获取管道输入(并且应该这样做),但尝试类似于

    ForEach-Object {
       # do something
    }
    

    使用命令行中的脚本时,实际上不起作用,如下所示:

    1..20 | .\test.ps1
    

    有办法吗?

    注意:我知道函数和过滤器。这不是我要找的。

    4 回复  |  直到 7 年前
        1
  •  38
  •   Bratch    10 年前

    这是可行的,可能还有其他方法可以做到:

    foreach ($i in $input) {
        $i
    }
    

    17:12:42 ps>1..20.\cmd-input.ps1



    --剪断--
    十八
    十九
    二十

    搜索“powershell$input variable”,您将找到更多信息和示例。
    这里有一对:
    PowerShell Functions and Filters PowerShell Pro!
    (请参阅“使用PowerShell特殊变量_$input_”一节)
    脚本、函数和脚本块都可以访问$input变量,该变量通过传入管道中的元素提供枚举器。

    $input gotchas « Dmitry’s PowerBlog PowerShell and beyond
    “……”基本上是在枚举器中$input,它提供对您拥有的管道的访问。”

    对于ps命令行,而不是 DOS命令行 Windows命令处理器。

        2
  •  107
  •   Shay Levy    12 年前

    在v2中,您还可以接受管道输入(按propertyname或byvalue)、添加参数别名等:

    function Get-File{
        param(  
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true)
        ]
        [Alias('FullName')]
        [String[]]$FilePath
        ) 
    
        process {
           foreach($path in $FilePath)
           {
               Write-Host "file path is: $path"
           }
        }
    }
    
    
    # test ValueFromPipelineByPropertyName 
    dir | Get-File
    
    # test ValueFromPipeline (byValue) 
    
    "D:\scripts\s1.txt","D:\scripts\s2.txt" | Get-File
    
     - or -
    
    dir *.txt | foreach {$_.fullname} | Get-File
    
        3
  •  23
  •   Keith Hill    15 年前

    您可以编写一个过滤器,它是类似这样的函数的特殊情况:

    filter SquareIt([int]$num) { $_ * $_ }
    

    或者您可以创建类似的函数,如下所示:

    function SquareIt([int]$num) {
      Begin {
        # Executes once before first item in pipeline is processed
      }
    
      Process {
        # Executes once for each pipeline object
        $_ * $_
      }
    
      End {
        # Executes once after last pipeline object is processed
      }
    }
    

    上面的定义是一个交互函数定义,或者如果脚本中有一个可以点在全局会话(或另一个脚本)中的话。但是,您的示例指示您需要一个脚本,因此这里的脚本直接可用(不需要点选):

      --- Contents of test.ps1 ---
      param([int]$num)
    
      Begin {
        # Executes once before first item in pipeline is processed
      }
    
      Process {
        # Executes once for each pipeline object
        $_ * $_
      }
    
      End {
        # Executes once after last pipeline object is processed
      }
    

    在PowerShell v2中,这与“高级函数”稍有不同,后者使用与编译的Cmdlet相同的参数绑定功能来嵌入函数。看到这个 blog post 作为差异的一个例子。另外请注意,在这个高级函数的例子中,您不使用$\来访问管道对象。使用高级函数,管道对象绑定到参数,就像使用Cmdlet一样。

        4
  •  7
  •   samthebest Ende Neu    12 年前

    以下是使用管道输入的脚本/函数的最简单示例。每个行为与管道到“echo”Cmdlet的行为相同。

    作为脚本:

    α-回波PIPS.PS1
      Begin {
        # Executes once before first item in pipeline is processed
      }
    
      Process {
        # Executes once for each pipeline object
        echo $_
      }
    
      End {
        # Executes once after last pipeline object is processed
      }
    
    #回声管2.ps1
    foreach ($i in $input) {
        $i
    }
    

    作为函数:

    Function Echo-Pipe {
      Begin {
        # Executes once before first item in pipeline is processed
      }
    
      Process {
        # Executes once for each pipeline object
        echo $_
      }
    
      End {
        # Executes once after last pipeline object is processed
      }
    }
    
    Function Echo-Pipe2 {
        foreach ($i in $input) {
            $i
        }
    }
    

    例如。

    PS > . theFileThatContainsTheFunctions.ps1 # This includes the functions into your session
    PS > echo "hello world" | Echo-Pipe
    hello world
    PS > cat aFileWithThreeTestLines.txt | Echo-Pipe2
    The first test line
    The second test line
    The third test line