string - PowerShell,管道兼容的 Select-String 函数
问题描述
这更多是因为我对管道和功能的理解不足,所以希望能得到帮助。举个例子:
Get-Service | Select-String win # fails
Get-Service | Out-String -Stream | Select-String win # works
我已经看到了为什么Out-String -Stream
需要的解释,但这让我有点沮丧,所以我想要一个oss
可以完成这Out-String -Stream
部分的函数。我的想法是这样的:
function oss { Out-String -Stream }
Get-Service | oss | Select-String win
但这失败了。有人可以告诉我如何使这项工作,即使oss
功能管道兼容?
然后,我们如何执行以下操作(显然这不起作用,但我真的很好奇如何实现)?
function slx { Out-String -Stream | Select-String <and allow all of the same switches as Select-String> }
Get-Service | slx win
那么,实际上,该部分slx
的变体是否Select-String
也总是如此Out-String -Stream
?
解决方案
我很感激你想学习,所以我不仅会给你一个可行的解决方案,还会解释一些事情。
您似乎对函数和管道的工作方式有基本的了解。如果您想了解有关它的更多信息,请查看about_Pipelines和about_Functions(以及相关的帮助主题),或者在评论中告诉我您特别想知道的内容。
如果您是 Powershell 的新手,您需要了解的一件事是它是基于对象的,而不是基于文本的。它是通过管道传递的对象,您应该像这样使用它们,而不是将它们转换为文本(除非用于文件输出)。
有关Select-String的文档特别指出,它用于在字符串和文件中查找文本。但这不是你在这里想要做的。正如我所说,使用对象,而不是文本。所以省略Out-String
. 过滤管道中对象的正确命令是Where-Object或其别名之一where
或?
.
例子:
Get-Service | where { $_.DisplayName -like *win* }
# in newer Powershell versions, this shorter syntax is also possible:
Get-Service | where DisplayName -like *win*
但是正如您特别询问有关使功能“管道感知”的那样,这可以通过多种方式完成。但是您的问题不仅在于从管道获取输入,还在于您将其传递给的方式Out-String
,因为如果您一次只传递一个项目,输出将会改变。
基本上你必须一次传递所有输入。因此,在您的情况下实现此目的的最简单方法是使用$Input自动变量:
function oss { $Input | Out-String -Stream }
如果您需要一次处理一个管道项,则有更多方法可以获取管道输入。例如一个高级功能:
function example {
process {
$_ # current item
}
}
您还可以使用参数属性将管道输入绑定到函数参数:
function example {
param(
[Parameter(ValueFromPipeline = $true)]
$InputObject
)
process {
$InputObject # current item
}
}
我能想到的最后一种方法是使用filter,这是一种特殊的函数,专门设计用于对每个管道元素执行操作:
filter example {
$_ # current item
}
要了解有关它的更多信息,我建议使用 google 搜索,它会快速为您提供有用的文章,例如为管道构建 PowerShell 函数或将管道输入合并到 PowerShell 函数中。
如果你真的想构建一个基本上是另一个 cmdlet 的包装器的方法,Out-String
或者Select-String
具有所有相同的开关,你应该看看proxy functions。但我认为这对于你想要做的事情来说太过分了:
function oss {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline = $true)]
[psobject]$InputObject
)
begin
{
try {
$outBuffer = $null
if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
{
$PSBoundParameters['OutBuffer'] = 1
}
# set -Stream switch always
$PSBoundParameters["Stream"] = $true
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\Out-String', [System.Management.Automation.CommandTypes]::Cmdlet)
$scriptCmd = {& $wrappedCmd @PSBoundParameters }
$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
$steppablePipeline.Begin($PSCmdlet)
} catch {
throw
}
}
process
{
try {
$steppablePipeline.Process($_)
} catch {
throw
}
}
end
{
try {
$steppablePipeline.End()
} catch {
throw
}
}
}
推荐阅读
- android - 在文本视图中从常规文本动画到粗体
- c# - 由于版本号不匹配,无法加载程序集
- c# - C# WinForms,具有半透明背景的工具提示
- sql - 将一个字段等分为2
- java - 蓝牙数据传输
- google-cloud-platform - 带有授权 API 密钥的 Google URL Shorter API 返回 403
- ios - WKWebView 从 Bundle 和 Document 目录加载文件
- grafana - 如何关闭表grafana中的自动生成列
- selenium - 如何在一个浏览器中运行相同功能文件的所有场景?使用硒,Java,黄瓜
- java - 带有 TLS 的 REST 客户端返回 SSLHandshakeException:收到致命警报:handshake_failure