Powershell Gotcha: Contains Operator

dev powershell, tip, match, contains, aws, lightsail, wordpress

I was working on a WordPress project recently. The project is to set up a WordPress blog using Amazon Lightsail service. I ended up blogging it here, but I want to talk about something else in this post.

Use Case: Filter results using -Contains operator

Amazon Lightsail comes with pre-packed applications, and you can create an instance by providing the blueprint id. You can search for blueprints by using the Get-LSBlueprintList cmdlet. It returns a list like this:

Screenshot of the terminal showing the results of Get-LSBlueprintList cmdlet

WordPress comes in two different blueprints: Single-site vs multi-site.

So my initial action was to filter the list based on the name containing the word “wordpress”. So I ran this script to get the results:

$applicationName = "wordpress"
Get-LSBlueprintList | Where-Object { 
    ($_.IsActive -eq $TRUE) -and
    ($_.Name -contains $applicationName)

To my surprise, this command returned the following result:

Screenshot of the terminal showing the results of Get-LSBlueprintList cmdlet with contains filter, filtering by the word wordpress and isactive set to true

The problem: Missing Wordpress blueprint

In the Amazon Lightsail dashboard, I can see the Wordpress Multisite exists:

Screenshot of Amazon Lightsail dashboard instance selection page with wordpress-multisite highlighted

I even captured the API call the dashboard makes when creating a WordPress Multisite instance and it looks like this:

Screenshot of captured API call showing wordpress_multisite as blueprintid

So how was it possible that wordpress_multisite blueprint id existed but I couldn’t get it via Get-LSBlueprintList? I thought there was something wrong with the cmdlet and even created a supported ticket for AWS!. To my surprise the problem was somewhere else.

The root cause: Contains operator works in mysterious ways!

As a C# developer, when I see “Contains”, I think of checking the existence of a substring in a string.

For example, check out this simple example:

Screenshot of C# application showing Contains function results

It’s checking whether or not the word “wordpress_multisite” contains the word “wordpress” and the answer is yes!

Now, let’s take a look at the Powershell-equivalent:

$wordpressMultisite = "wordpress_multisite"
$containsWordpress = $wordpressMultisite -contains "wordpress"

and here is the result:

Screenshot of Powershell script showing Contains operator results with substring

In this case, the answer is no!

The reason is contains operator is by design meant to be used to search collections for a string. For example, the following example illustrates the intended use:

$listOfApplications = "wordpress", "lamp", "nodejs"
$listOfApplicationsContainsWordpress = $listOfApplications -contains "wordpress"

and the result is:

Screenshot of Powershell script showing Contains operator results over a list of strings

The solution: Match Operator

The solution is using the match operator for substrings. In my original script, all I had to do was replace contains with match and got the expected results.

Final script:

$applicationName = "wordpress"
Get-LSBlueprintList | Where-Object { 
    ($_.IsActive -eq $TRUE) -and
    ($_.Name -match $applicationName)

Output of the script:

Screenshot of Powershell script showing both wordpress and wordpress_nultisite results


So there you have it: Always read the documentation!

As Powershell is based on the .NET framework, I instinctively assumed contains would search a string for substrings, but it works entirely differently.

I lost some time but learned a valuable lesson. I hope you find this post useful too, and it prevents the same thing from happening to you too.