管道单个对象并在没有 Foreach 对象的情况下处理它
Pipe a single object and process it without For-EachObject
原问题
我通过管道传输单个字符串并使用 For-EachObject
对其进行处理,如下所示:
"Test" | % { $_.Substring(0,1) }
使用 For-EachObject
处理单个管道项目似乎是错误的,部分原因是它会误导未来的代码维护者。不过,我不知道还有什么其他方法可以在说 "it's just a single item." 的同时捕获字符串。例如,这不起作用。
"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
部分周围放置多个括号看起来很难看。
别名
curl
是 Invoke-WebRequest
select
是 Select-Object
-expand
是 ExplandProperty
?
是 Where-Object
%
是 For-EachObject
如果您正在创建单一用途的代码,您可以同时控制输入和输出,并且始终只有一个对象,那么使用管道就太过分了,而且不太合适。只需将字符串作为参数传递给您的函数即可。
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 有一个 shorthand 用于编写一个从管道获取一个参数并且只包含一个进程块的函数。
filter f {
$_.SubString(0,1)
}
PS> '123','abc','#%@' | f
1
a
#
原问题
我通过管道传输单个字符串并使用 For-EachObject
对其进行处理,如下所示:
"Test" | % { $_.Substring(0,1) }
使用 For-EachObject
处理单个管道项目似乎是错误的,部分原因是它会误导未来的代码维护者。不过,我不知道还有什么其他方法可以在说 "it's just a single item." 的同时捕获字符串。例如,这不起作用。
"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
部分周围放置多个括号看起来很难看。
别名
curl
是Invoke-WebRequest
select
是Select-Object
-expand
是ExplandProperty
?
是Where-Object
%
是For-EachObject
如果您正在创建单一用途的代码,您可以同时控制输入和输出,并且始终只有一个对象,那么使用管道就太过分了,而且不太合适。只需将字符串作为参数传递给您的函数即可。
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 有一个 shorthand 用于编写一个从管道获取一个参数并且只包含一个进程块的函数。
filter f {
$_.SubString(0,1)
}
PS> '123','abc','#%@' | f 1 a #