如何用Where-Object/Wildcards匹配多个字符串?

How to match multiple strings with Where-Object/Wildcards?

我被要求使用 Get-Command 提取命令,其中动词是 getsetconvertTo 之一,名词以 CXV.

这是我目前所拥有的:

Get-Command | ?{$_ -like "set[-][CXV]*"} #Prints all commands that start with Set

我正在努力搜索 setgetConvertTo 中的多个动词。我尝试了几种不同的方法,但都无济于事。

这是我的做法...使用 Get-Command 内置参数 = -Verb.

代码的作用...

  • 创建要匹配的动词列表
  • 创建一个正则表达式 char-at-start-of-string 列表模式
  • 抓取具有所需动词的命令
  • 过滤名词以所需字符开头的命令
  • Verb 然后按 Noun
  • 对结果命令进行排序

代码...

$VerbList = @(
    'get'
    'set'
    'convertto'
    )

$Regex_NounStartsWith = '^[cxv]'

Get-Command -Verb $VerbList |
    Where-Object {
        $_.Noun -match $Regex_NounStartsWith
        } |
    Sort-Object -Property Verb, Noun

截断的结果...

CommandType     Name                                               Version    Source                                                                                      
-----------     ----                                               -------    ------                                                                                      
Cmdlet          ConvertTo-Csv                                      3.1.0.0    Microsoft.PowerShell.Utility                                                                
Cmdlet          ConvertTo-Xml                                      3.1.0.0    Microsoft.PowerShell.Utility                                                                
Function        Get-CallerPreference                               5.31.0     PSLog                                                                                       
Function        Get-CallerPreference                               5.22.0     PSLog                                                                                       
Cmdlet          Get-Certificate                                    1.0.0.0    PKI                                                                                         
Cmdlet          Get-CertificateAutoEnrollmentPolicy                1.0.0.0    PKI                                                                                         
Cmdlet          Get-CertificateEnrollmentPolicyServer              1.0.0.0    PKI                                                                                         
Cmdlet          Get-CertificateNotificationTask                    1.0.0.0    PKI                                                                                         
Cmdlet          Get-ChildItem                                      3.1.0.0    Microsoft.PowerShell.Management                                                              
[*...snip...*]     

你一开始是正确的,但是,-like 只允许你匹配通配符模式,而 -match 允许你匹配正则表达式模式,你的正则表达式只需要一点点调整:

Get-Command | ?{$_ -match "((^set)|(^get)|(^convertto))-[CXV]+"}

这可以进一步缩短为:

Get-Command | ?{$_ -match "((^[sg]et)|(^convertto))-[CXV]+"}

如果您想要命令的排序输出:

Get-Command | ?{$_ -match "((^[sg]et)|(^convertto))-[CXV]+"} | Sort

参考:About Comparison Operators

Get-Command -Name *-[CXV]* | Where-Object Verb -in Get, Set, ConvertTo

另一个选项,使用单个 Where-Object 脚本块,完全避免模式匹配($_.Noun[0] returns 名词部分的第一个字符):

Get-Command | 
  Where-Object { 
    $_.Noun[0] -in 'C', 'X', 'V' -and $_.Verb -in 'Get', 'Set', 'ConvertTo'
  }

另一种选择是使用 regular expression, as shown in - 尽管使用上面的通配符/面向对象的解决方案可以避免其增加的复杂性。


至于你试过的

$_ -like "set[-][CXV]*"

通配符表达式不够复杂,无法匹配给定的一组子字符串(只能匹配一组单个字符,如您尝试的[CXV])。

解决方案是只匹配 *-[CXV]* 以过滤名词部分,并为动词部分添加与 -and 附加 比较(例如如 $_.Verb -in 'Get', 'Set', 'ConvertTo',如上所示),或使用 正则表达式 ,如 Suraj 的回答所示。