pyte
pyte

Reputation: 59

PowerShell - Removing Items from Array

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?

Upvotes: 3

Views: 6524

Answers (3)

js2010
js2010

Reputation: 27423

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

Upvotes: 2

Tomalak
Tomalak

Reputation: 338208

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.

Upvotes: 3

user459872
user459872

Reputation: 24592

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

Upvotes: 3

Related Questions