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

Time:11-28

I'm asked to extract commands using Get-Command, where the verb is one of get, set or convertTo and the noun starts with any of C, X or V.

This is what I have so far:

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

I am struggling to search for multiple verbs that are either set, get, or ConvertTo. I have attempted several different methods but to no avail.

CodePudding user response:

here is how i would do it ... using a Get-Command built in parameter = -Verb.

what the code does ...

  • creates the list of verbs to match
  • creates a regex char-at-start-of-string list pattern
  • grabs the commands that have the desired verbs
  • filters for the commands with nouns that start with the desired chars
  • sorts the resulting commands by Verb then by Noun

the code ...

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

$Regex_NounStartsWith = '^[cxv]'

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

truncated results ...

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...*]     

CodePudding user response:

You started off correctly, however, -like lets you match only wildcard patterns whereas -match let you match regex patterns and your regex just needs a little tweaking:

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

This can be further shortened to:

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

If you want a sorted output of the commands:

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

Ref: About Comparison Operators

CodePudding user response:

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

Another option, with a single Where-Object script block that avoids pattern matching altogether ($_.Noun[0] returns the noun part's first character):

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

Yet another option is to use a regular expression, as shown in Suraj's helpful answer - though its added complexity can be avoided with the wildcard / object-oriented solutions above.


As for what you tried:

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

Wildcard expressions aren't sophisticated enough to match one of a given set of substrings (only a set of individual characters can be matched, such [CXV] in your attempt).

The solution is to either match just against *-[CXV]* to filter the noun part and add an additional comparison with -and for the verb part (such as $_.Verb -in 'Get', 'Set', 'ConvertTo', as shown above), or to use a regular expression instead, as shown in Suraj's answer.

  • Related