3

I'm trying to remove items from an array that match special keywords. My array looks something like this:

$Printers =@('Printer Phone', 'Printer Building1', 'Printer XML', 'Printer Station', ...) 

I want to remove all entries that match parts of certain strings, like filtering out every item that has "Phone" or "XML" in it's value. I thought of something like this but I'm not quiet sure if I'm on the right track:

$contains = @('Phone', 'XML')
$Printers -Filter * | Where-Object { $contains -contains $_.name }

Is there a simple way to achieve this?

1
  • 1
    $Printers |Select-String -NotMatch $Contains Commented Sep 6, 2021 at 11:55

3 Answers 3

3

Here is one way to do this.

> $contains = @('Phone', 'XML')
> $Printers = @('Printer Phone','Printer Building1','Printer XML', 'Printer Station')
> $Printers | Where-Object { $_ -Match ($contains -Join "|") }
Printer Phone
Printer XML
> $Printers | Where-Object { $_ -notMatch ($contains -Join "|") }
Printer Building1
Printer Station
Sign up to request clarification or add additional context in comments.

1 Comment

It's an elegant solution, but it would help if you explained it a bit and mentioned the potential need to apply [regex]::Escape() to the search terms (not necessary with the sample input). Also, it would help if you allowed readers to copy and paste the solution as-is in order to try it, in a single operation, without having to remove the > prefixes or having to copy and paste the relevant part of each line individually.
3

Three remarks

  • You don't need @() to make arrays. The comma is what makes arrays, the @() is redundant here.
  • The PowerShell -contains operator does not check whether a string contains a substring. It checks whether an array contains a value.
    Using the .NET .Contains() method works for substring checks, but be aware, it's case-sensitive. Lower-case your strings if you need case-insensitive comparisons (good enough and easier than doing it "by the book").
  • Any value that you produce in a {} script block and don't assign to a variable, will become part of that script block's output. That's how the Where-Object block below works.

Code:

$Printers = 'Printer Phone','Printer Building1','Printer XML', 'Printer Station' 
$contains = 'Phone','XML'

$Printers | Where-Object { 
    $printer = $_
    $contains | Where-Object {  $printer.Contains($_) }
}

Where-Object considers non-empty output as $true. So filtering $contains down to something (or nothing) will decide whether the $Printers value makes it. The above prints

Printer Phone
Printer XML

You could use -match, but then you would have to start worrying about regex-escaping your $contains values properly to avoid run-time errors.

1 Comment

Just as a matter of practice, it's always a good idea to add @() around your arrays, even if it looks redundant. Arrays with one element otherwise easily get turned into single items instead of arrays. For example, (GetList) + "XML" is very different than @(GetList) + "XML", if the GetList function returns an array of only one element.
2

You can have an array of patterns with select-string. But select-string's output is a matchinfo object (unless it's converted to a string) and the line property has the original string examined.

$patterns = echo Phone XML
$printers = 'Printer Phone', 'Printer Building1', 'Printer XML',
  'Printer Station'
$printers | select-string $patterns | % line
Printer Phone
Printer XML

Unfortunately, -contains is a frequent point of confusion.

'printer station' -contains 'station'

False


-split 'printer station' -contains 'station'

True

1 Comment

Nice, though it's safer to add -SimpleMatch in this case, for literal substring searches. In PowerShell (Core) 7+, -Raw is now available for direct output of the matching lines as strings; e.g. $printers | select-string -Raw -SimpleMatch $patterns

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.