Steffen Bauer
Steffen Bauer

Reputation: 145

match array to multiple regex (from array)

I have an array with Strings, let´s say

$data = @(
"Haus",
"Maus",
"Laus",
"Schnitzel",
"Elefant"
)

I want to check it against multiple Regex from an array.

$regexChecks = @(
".*aus.*",
".*fant.*"
)

I tried something like this

$test = $data |? {$regexChecks -notmatch $_}

Write-Host $test

I expect only the String "Schnitzel" as output.

Upvotes: 5

Views: 4219

Answers (2)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200233

Regular expression matches are much slower operations that literal comparisons (-eq) or even wildcard matches (-like), so you should reduce the number of comparisons as much as possible. Since you have an array of regular expressions you can simply merge them into a single one like this:

$regexChecks = '.*aus.*', '.*fant.*'
$re = $regexChecks -join '|'

If you want multiple literal strings matched you can tell PowerShell to escape them first (just in case they contain special characters like dots, square brackets, etc.):

$re = ($regexChecks | ForEach-Object {[regex]::Escape($_)}) -join '|'

Also, you don't need to add leading and trailing .* to your expressions, because regular expressions aren't anchored by default. Just leave them out.

$regexChecks = 'aus', 'fant'
$re = ($regexChecks | ForEach-Object {[regex]::Escape($_)}) -join '|'

You also don't need Where-Object or ForEach-Object to enumerate the elements of an array, because PowerShell operators work as enumerators themselves. Simply use the operator on the array directly:

$test = $data -match $re

Upvotes: 5

SimonS
SimonS

Reputation: 1973

you can put the regex as a string. This would only return Schnitzel

$data = @(
"Haus",
"Maus",
"Laus",
"Schnitzel",
"Elefant"
)

$Regex = '.*Schnitzel.*'

$test = $data | ? { $_ -match $Regex }

Write-Host $test

if you want to check more than one regex, use | to seperate them

This would output Schnitzel and Maus

$Regex = '.*Schnitzel.*|.*Maus.*'

This would return Schnitzel, Maus, Laus and Haus

$Regex = '.*Schnitzel.*|.*aus.*'

EDIT:

You can also have a regex array, and join them with |:

$RegexArray = @(
    '.*Schnitzel.*',
    '.*Maus.*'
)

$Regex = $RegexArray -join '|'

$test = $data | ? { $_ -match $Regex }

Upvotes: 8

Related Questions