3

I have two arrays, $a and $b, within array $a is a string which could partially match one of the entries in $b, assuming I could use a wildcard:

$a = "1", "Computer Name", "2"
$b = "3", "4", "Full Computer Name Here"

foreach ($line in $a) {
    foreach ($line2 in $b) {
         where "*$line*" -like "*$line2*"
    }
}

I've got here after trying all the simple 'this array matches that array', into foreach for one array, then tried all the Select-String to Compare-Object $line $line2 -ExcludeDifferent -IncludeEqual -PassThru, but can't get anything to work.

Ideally, it'd return 'Full Computer Name Here' where it matches.

3 Answers 3

7

Have you tried this?

$a = "1","Computer Name","2"
$b = "3","4","Full Computer Name Here"
foreach ($line in $a ) {
    $b -match $line
}

EDIT: Probably not the best answer despite it's simplicity as illustrated by @Ansgar in the comments. Sometimes PowerShell is so inconsistent it makes me wonder why I still use it.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for reminding me that comparison operators implicitly work as enumerators too. Note, however, that the -match operator does a regular expression match, which might yield undesired results if a comparison string contains special characters.
Yes indeed. I knew I was missing something about -match not being the best option. But since all array elements are string, I think it will survive this one.
$a = "foo."; $b = "foo.example.org", "foobar.example.org"
Hmm? The behavior is perfectly consistent. The -match operator does regular expression matches, so the match string is handled as a regular expression. It's not a bad thing, just something you need to be aware of when using match strings from some other source. Escape the string and everything should work just fine.
6

Where-Object doesn't work that way. It reads from a pipeline that you don't have in your code. Also, your comparison is backwards, and you must not add wildcard characters to the reference value.

Change your code to something like this:

foreach ($line in $a) {
    $b | Where-Object { $_ -like "*${line}*" }
}

or like this:

foreach ($line in $a) {
    foreach ($line2 in $b) {
        if ($line2 -like "*${line}*") { $line2 }
    }
}

and it will do what you expect.

Edit:

I keep forgetting that comparison operators also work as enumerators, so the latter example could be simplified to something like this (removing the nested loop and conditional):

foreach ($line in $a) {
    $b -like "*${line}*"
}

Comments

4
$b | Where {$_ | Select-String $a}

Updated 2018-06-23

Credits for LotsPings' comment to minimize it further to:

Apparently, Select-String has already both iterators in itself and therefore it can be simplified to just:

$b | Select-String $a

PS C:\> $a = "1", "Computer Name", "Other Name"
PS C:\> $b = "Computer", "4", "Full Computer Name Here", "something else", "Also full computer name here"
PS C:\> $b | Select-String $a

Full Computer Name Here
Also full computer name here

3 Comments

That isn't very different from $b | Select-String $a (aside from some blank lines) but the RegEx restrictions mentioned by @AnsgarWiechers apply also (+1)
@LotPings, you completely right, my answer was evolving yesterday when I was writing it but didn't go to the bottom as I needed to leave in a hurry. I have aggravated the input arrays to prove the result is correct and changed the answer accordingly.
You may want to add the parameter -SimpleMatch, otherwise your code might produce incorrect matches with input containing special characters (see here).

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.