【问题标题】:Pipe a single object and process it without For-EachObject管道单个对象并在没有 Foreach 对象的情况下对其进行处理
【发布时间】:2015-03-06 23:42:57
【问题描述】:

原始问题

我用管道处理单个字符串并使用For-EachObject 处理它,如下所示:

 "Test" | % { $_.Substring(0,1) }

使用For-EachObject 处理单个管道项似乎是错误的,部分原因是它会误导未来的代码维护者。不过,我不知道有什么其他方法可以在说“它只是一个项目”的同时捕获字符串。例如,这不起作用。

"Test" | $_.Substring(0,1)
"Test" | { $_.Substring(0,1) }

如何处理单个对象同时指示我只需要一个对象?

编辑:添加实际用例

以上是我实际尝试完成的简化版本。我收到了一篇维基百科文章的第一段,它是a larger function that saves the result to a file 的一部分。

curl "www.wikipedia.org/wiki/Hope,_British_Columbia" | 
    select -expand allelements | 
    ? { $_.id -eq "mw-content-text" } | 
    select -expand innerHTML | 
    % { 
        $i = $_.IndexOf("<P>"); 
        $j = $_.IndexOf("</P>"); 
        $_.Substring($i, $j - $i) -replace '<[^>]*>'
     } 

需要处理单个对象的部分遵循select -expand innerHtml 表达式。管道是我的首选方式,因为在 curl 部分周围加上多个括号看起来很难看。

别名

  • curlInvoke-WebRequest
  • selectSelect-Object
  • -expandExplandProperty
  • ?Where-Object
  • %For-EachObject

【问题讨论】:

  • "Test".SubString(0,1) 适合你吗?
  • 确实如此。但有时,管道似乎是最好的工具。
  • 管道是为对象流设计的。使用 foreach 迭代它们是非常自然的。如果你写了一个假设管道中只有一个对象的函数,如果前面的命令放入了多个项目,它会做什么?
  • 补充一下 Ryan 所说的,'test'.substring(0,1) 的性能比使用管道要好得多。
  • @RyanBemrose 说得好。问题是,我没有写函数。我正在写一系列管道表达式(这是正确的术语吗?)

标签: powershell code-readability


【解决方案1】:

如果您要创建同时控制输入和输出的单一用途代码,并且总是只有一个对象,那么使用管道是矫枉过正的,而且并不合适。只需将字符串作为参数传递给您的函数。

function f([String]$s) {
  $s.Substring(0,1)
}
PS> f "Test"
T

如果您要构建一个通用函数来从管道中获取输入,那么您的函数需要考虑流中的多个对象。幸运的是,PowerShell 使用Process{} 块有一种自然的方式来执行此操作,该块对输入管道中的每个项目执行一次。

function f {
  param(
    [Parameter(ValueFromPipeline=$true)]
    [String]$item
  )
  process {
    $item.Substring(0,1)
  }
}
PS> '123','abc','#%@' | f
1
a
#

这是一个足够常见的函数,PowerShell 有一种简写方式来编写一个函数,该函数从管道中获取一个参数并且只包含一个进程块。

filter f {
  $_.SubString(0,1)
}
PS> '123','abc','#%@' | f
1
a
#

【讨论】:

    猜你喜欢
    • 2014-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-28
    • 1970-01-01
    相关资源
    最近更新 更多