How to exit from ForEach-Object in PowerShell

前端 未结 9 1746
北海茫月
北海茫月 2020-11-27 20:30

I have the following code:

$project.PropertyGroup | Foreach-Object {
    if($_.GetAttribute(\'Condition\').Trim() -eq $propertyGroupConditionName.Trim()) {
           


        
相关标签:
9条回答
  • 2020-11-27 21:24

    Since ForEach-Object is a cmdlet, break and continue will behave differently here than with the foreach keyword. Both will stop the loop but will also terminate the entire script:

    break:

    0..3 | foreach {
        if ($_ -eq 2) { break }
        $_
    }
    echo "Never printed"
    
    # OUTPUT:
    # 0
    # 1
    

    continue:

    0..3 | foreach {
        if ($_ -eq 2) { continue }
        $_
    }
    echo "Never printed"
    
    # OUTPUT:
    # 0
    # 1
    

    So far, I have not found a "good" way to break a foreach script block without breaking the script, except "abusing" exceptions:

    throw:

    try {
        0..3 | foreach {
            if ($_ -eq 2) { throw }
            $_
        }
    } catch { }
    echo "End"
    
    # OUTPUT:
    # 0
    # 1
    # End
    

    The alternative (which is not always possible) would be to use the foreach keyword:

    foreach:

    foreach ($_ in (0..3)) {
        if ($_ -eq 2) { break }
        $_
    }
    echo "End"
    
    # OUTPUT:
    # 0
    # 1
    # End
    
    0 讨论(0)
  • 2020-11-27 21:29

    Answer for Question #1 - You could simply have your if statement stop being TRUE

    $project.PropertyGroup | Foreach {
        if(($_.GetAttribute('Condition').Trim() -eq $propertyGroupConditionName.Trim()) -and !$FinishLoop) {
            $a = $project.RemoveChild($_);
            Write-Host $_.GetAttribute('Condition')"has been removed.";
            $FinishLoop = $true
        }
    };
    
    0 讨论(0)
  • 2020-11-27 21:29

    I found this question while looking for a way to have fine grained flow control to break from a specific block of code. The solution I settled on wasn't mentioned...

    Using labels with the break keyword

    From: about_break

    A Break statement can include a label that lets you exit embedded loops. A label can specify any loop keyword, such as Foreach, For, or While, in a script.

    Here's a simple example

    :myLabel for($i = 1; $i -le 2; $i++) {
            Write-Host "Iteration: $i"
            break myLabel
    }
    
    Write-Host "After for loop"
    
    # Results:
    # Iteration: 1
    # After for loop
    

    And then a more complicated example that shows the results with nested labels and breaking each one.

    :outerLabel for($outer = 1; $outer -le 2; $outer++) {
    
        :innerLabel for($inner = 1; $inner -le 2; $inner++) {
            Write-Host "Outer: $outer / Inner: $inner"
            #break innerLabel
            #break outerLabel
        }
    
        Write-Host "After Inner Loop"
    }
    
    Write-Host "After Outer Loop"
    
    # Both breaks commented out
    # Outer: 1 / Inner: 1
    # Outer: 1 / Inner: 2
    # After Inner Loop
    # Outer: 2 / Inner: 1
    # Outer: 2 / Inner: 2
    # After Inner Loop
    # After Outer Loop
    
    # break innerLabel Results
    # Outer: 1 / Inner: 1
    # After Inner Loop
    # Outer: 2 / Inner: 1
    # After Inner Loop
    # After Outer Loop
    
    # break outerLabel Results
    # Outer: 1 / Inner: 1
    # After Outer Loop
    

    You can also adapt it to work in other situations by wrapping blocks of code in loops that will only execute once.

    :myLabel do {
        1..2 | % {
    
            Write-Host "Iteration: $_"
            break myLabel
    
        }
    } while ($false)
    
    Write-Host "After do while loop"
    
    # Results:
    # Iteration: 1
    # After do while loop
    
    0 讨论(0)
提交回复
热议问题