1

I'm trying to avoid using nested ForEach Loop as part of a larger code. To do this, I'm using the -notcontains operator. Basically, I want to see if a substring exists within a string within an array. If it exists, do nothing, if it does not exist, print "Not Found".

Here is the code...

$arr = @('"value11","value21","value31"','"value12","value22","value32"','"value13","value23","value33"')

if ($arr -notcontains "*`"value24`"*")
{
    Write-Host "Not Found"
}

if ($arr -notcontains "*`"value22`"*")
{
    Write-Host "Not Found 2"
}

We can see that value24 is not within any strings of the array. However, value22 is within the 2nd string in the array.

Therefor the results should output the following...

Not Found

However, instead I see the following output...

Not Found
Not Found 2

Can anyone tell me why this is happening?

3
  • FYI, Looks like the contains operator requires an exact match of the item within the array, and wildcards are useless - computerperformance.co.uk/powershell/…. I have an answer brewing shortly, and it's definitely not the cleanest solution. If someone has a better solution I would love to hear it. Commented Mar 4, 2016 at 17:04
  • Do you want to react to each match/notmatch or just if it is present in the array period? Commented Mar 4, 2016 at 17:21
  • basically if the substring does not exist within any string of the array, it should only print "Not Found" once. If it does exist within the array, don't print anything... Commented Mar 4, 2016 at 17:23

3 Answers 3

3

-contains and -notcontains don't operate against patterns.

Luckily, -match and -like and their negative counterparts, when used with an array on the left side, return an array of the items that satisfy the condition:

'apple','ape','vape' -like '*ape'

Returns:

ape
vape

In an if statement, this still works (a 0 count result will be interpreted as $false):

$arr = @('"value11","value21","value31"','"value12","value22","value32"','"value13","value23","value33"')

if ($arr -notlike "*`"value24`"*")
{
    Write-Host "Not Found"
}
Sign up to request clarification or add additional context in comments.

8 Comments

Well there goes my answer draft :)
@Matt haha you usually beat me I think
the problem with this, if you change that value24 in the if statement to value22, it will still say "Not Found". I believe using the -like or the -match does not check each item individually. See my complicated answer for correct results...
"*`"value24`"*" should just be '*"value24"*' no escaping.
nope, it returns "Not Found" if I change that value in the if statement to '*"value22"*'. Instead, it should not print anything.
|
2

My take on a solution:

($arr | foreach {$_.contains('"value24"')}) -contains $true

Using the V3 .foreach() method:

($arr.ForEach({$_.contains('"value24"')}).contains($true))

And yet another possibility:

[bool]($arr.where({$_.contains('"value24"')}))

6 Comments

I thought the same thing, but look closer, it's a (confusing) array of strings, where the strings are single quotes and then contain what looks like an array of double quoted strings. Unless it's so confusing that I'm reading it wrong too..
You're right. It's actually more of a substring search. But the solution still appears to work.
Ah perfect. I just had to change -contains to -notcontains. But this is exactly what I'm looking for... Thanks :D
I saw the comment about not using the pipeline (appears to have been deleted now, so I'm not sure what that was about), but if it's a problem then no worries. You're using V3, so you also have the option of using the .foreach() method of $arr. Update the answer with an example.
The issue was I was passing a variable $_.USR_ID from the previous pipeline. I was still able to use your line of code, I just had to add a line (prior to your line) $searchValue = $_.USR_ID. Then change If (($resultsFileContents | foreach {$_.contains($_.USR_ID)}) -notcontains $true) to If (($resultsFileContents | foreach {$_.contains($searchValue)}) -notcontains $true). I didn't feel this was worth mentioning though, since it was not related to the original question. Apologies for the previous comment I removed.
|
0

Edit for clearer answer on what I'm looking for...

This is the only way I'm able to figure this out so far. I hope there is a much cleaner solution...

$arr = @('"value11","value21","value31"','"value12","value22","value32"','"value13","value23","value33"')

$itemNotFound = $true
ForEach ($item in $arr)
{
    If ($itemNotFound)
    {
        If ($item -like "*`"value24`"*")
        {
            $itemNotFound = $false
        }
    }

}
if ($itemNotFound)
{
    Write-Host "Not Found value24"
}


$itemNotFound = $true
ForEach ($item in $arr)
{
    If ($itemNotFound)
    {
        If ($item -like "*`"value22`"*")
        {
            $itemNotFound = $false
        }
    }

}
if ($itemNotFound)
{
    Write-Host "Not Found value22"
}

output will be:

Not Found value24

Comments

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.