How to match any part of a property string using Where-Object

6.2k views Asked by At

I have an array $array with many elements, an example looks like this:

ProfileID         : 100
UID               : 17
Name              : SharePoint
Description       : SharePoint Server Description

Now I am trying to filter by Name property, string to match is:

$string
SharePoint Policy Assignment

I have tried:

$array | Where-Object {$_.Name -like "$string"}
no match

$array | Where-Object {$_.Name -like "$string*"}
no match

$array | Where-Object {$_.Name -match "$string"}
no match

Is this possible using PowerShell? What am I missing?

2

There are 2 answers

0
FoxDeploy On BEST ANSWER

The -like operator in PowerShell is used for a wildcard match, so you need to use the wildcard character, the asterisk, *.

Imagine this scenario, where I'm trying to match a particular Windows Service.

$svcs = Get-Service | Select-Object -first 15

C:\temp\blog> $svcs

Status   Name               DisplayName                           
------   ----               -----------                           
Stopped  AJRouter           AllJoyn Router Service                
Stopped  ALG                Application Layer Gateway Service     
Running  AMD External Ev... AMD External Events Utility           
Stopped  AppIDSvc           Application Identity                  
Running  Appinfo            Application Information               
Stopped  AppMgmt            Application Management                
Stopped  AppReadiness       App Readiness                         
Stopped  AppVClient         Microsoft App-V Client                
Stopped  AppXSvc            AppX Deployment Service (AppXSVC)     
Stopped  aspnet_state       ASP.NET State Service                 
Stopped  AssignedAccessM... AssignedAccessManager Service         
Running  AsSysCtrlService   ASUS System Control Service           
Running  AudioEndpointBu... Windows Audio Endpoint Builder        
Running  Audiosrv           Windows Audio                         
Running  AUEPLauncher       AMD User Experience Program Launcher  

To use the -Like operator to get a match, I have to provide a Wildcard Character, like this.

$svcs | Where-Object Name -like App*

Status   Name               DisplayName                           
------   ----               -----------                           
Stopped  AppIDSvc           Application Identity                  
Running  Appinfo            Application Information               
Stopped  AppMgmt            Application Management                
Stopped  AppReadiness       App Readiness                         
Stopped  AppVClient         Microsoft App-V Client                
Stopped  AppXSvc            AppX Deployment Service (AppXSVC)     

Try your operation using a WildCard, and I bet it will work :)

One other thing I noted, your $string is equal to SharePoint Policy Assignment, but the column you're comparing on of .Name is just SharePoint.

0
mklement0 On

To complement FoxDeploy's helpful answer:

With collections that are already are in memory or easily fit, you can use member-access enumeration for a more convenient syntax that also results in much faster execution:

@($array.Name) -like $string  # returns sub-array of matching elements

-like, when given an array as the LHS, acts as a filter: only those array elements that match the wildcard expression on the RHS are returned (also as an array).

Note the need for @(...) to ensure that $array.Name is an array, because a single-element array would result in the .Name property getting returned as a scalar (a single string), in which case -like would return a Boolean ($true or $false) rather than acting as a filter.


Also note that many PowerShell cmdlets directly support wildcard expressions as parameter values:

Taking Get-Service as an example, its (implied) -Name parameter supports wildcards:

Get-Service *router*  # returns all services whose Name contains "router"

To determine a given cmdlet parameter's wildcard support:

PS> Get-Help Get-Service -Parameter Name

-Name <String[]>
    Specifies the service names of services to be retrieved. Wildcards are permitted. By default, this cmdlet gets all of the services on the computer.

    Required?                    false
    Position?                    1
    Default value                None
    Accept pipeline input?       True (ByPropertyName, ByValue)
    Accept wildcard characters?  false

It should be the Accept wildcard characters? value being true that indicates support for wildcard expressions, however, this is unfortunately not reliable, so also check the parameter description; here, the descriptin part Wildcards are permitted provides the information.
GitHub issue #4716 describes the problem and asks to make the programmatic discoverability of wildcard support reliable.