Shahboz
Shahboz

Reputation: 546

How to break in nested foreach loop in powershell

I have two lists with the same length. I need to iterate so that the first item in the list A matches the first item in the list B. For that I've created a nested foreach loop, that looks like this:

$nodes_table = "a","b","c"
$nodes_list = "a","b","c"

     :Outer foreach ($item in $nodes_table) {
        foreach($node in $nodes_list)
        {
            if($node -eq $item)
            {
                Write-Output "$node hostname matches in vTM"
                break :Outer
            }           
        }        
    }

Problem: In the first iteration, it matches. But in the second iteration, the inner loop doesn't go to the second item, it resets again.

First iteration: $node = a equals $item = a
Second iteration: $node = a not equals to $item = b.

As you can see, in the second iteration inner loop didn't iterate, it reset back to a.

Upvotes: 2

Views: 10206

Answers (2)

STLDev
STLDev

Reputation: 6174

I changed your example code as follows:

$nodes_table = "a","b","c"
$nodes_list = "a","b","c"

:Outer foreach ($item in $nodes_table) 
{
    foreach($node in $nodes_list)
    {
        Write-Output "item = $item, node = $node" # display values being compared
        if($node -eq $item)
        {
            Write-Output "$node hostname matches in vTM"
            break :Outer
        }           
    }
}

This produces the following output:

item = a, node = a
a hostname matches in vTM
item = b, node = a
item = b, node = b
b hostname matches in vTM
item = c, node = a
item = c, node = b
item = c, node = c
c hostname matches in vTM

Looks to me like it's behaving correctly.

EDIT

As pointed out by Bruce Payette's answer below, there is a defect in the original code that I copied into my example above. The break :Outer statement is incorrect, because the object of a break should either be nothing or the name of a label. The colon (:) character should not be there. PowerShell ignores this error and behaves as if there is no label on the break statement, thereby breaking the inner loop, not the outer loop. Removing the colon, which makes the line break Outer, you will see that the code jumps immediately to the end of the outer for loop during the first iteration of the outer loop and the first iteration of the inner loop.

Upvotes: 0

Bruce Payette
Bruce Payette

Reputation: 2639

There are two problems here. First, if you have a label like:Outer foreach(... the name of the label is just Outer so when you reference it in a break statement, you specify break Outer not break :Outer (might just be a typo). Second, you need to use the continue statement not the break statement. The continue statement resumes execution at the next iteration. The updated code looks like:

$nodes_table = "a","b","c"
$nodes_list = "a","b","c"

:Outer foreach ($item in $nodes_table) {
    foreach($node in $nodes_list)
    {
        if($node -eq $item)
        {
            Write-Output "$node hostname matches in vTM"
            continue Outer
        }           
    }        
}

Upvotes: 6

Related Questions