2012-04-23 3 views
41

У меня есть следующий код:Как выйти из ForEach-Object в PowerShell

$project.PropertyGroup | Foreach { 
    if($_.GetAttribute('Condition').Trim() -eq $propertyGroupConditionName.Trim()) { 
     $a = $project.RemoveChild($_); 
     Write-Host $_.GetAttribute('Condition')"has been removed."; 
    } 
}; 

Вопрос № 1: Как выйти из ForEach? Я пробовал использовать «break» и «continue», но это не сработало.

Вопрос №2: Я обнаружил, что могу изменить список в цикле foreach ... Мы не можем сделать это как на C# ... Почему PowerShell позволяет нам это делать?

ответ

69

Продукт №1. Ввод break в цикле foreach завершает цикл, но он не останавливает конвейер. Похоже, вы хотите что-то вроде этого:

$todo=$project.PropertyGroup 
foreach ($thing in $todo){ 
    if ($thing -eq 'some_condition'){ 
     break 
    } 
} 

Пункт № 2. PowerShell позволяет вам изменять массив в цикле foreach над этим массивом, но эти изменения не вступают в силу до выхода из цикла. Попробуйте выполнить приведенный ниже код для примера.

$a=1,2,3 
foreach ($value in $a){ 
    Write-Host $value 
} 
Write-Host $a 

Я не могу прокомментировать, почему авторы PowerShell позволили, но большинство других языков сценариев (Perl, Python и оболочки) позволяют подобные конструкции.

+0

Я думаю, вы хотели добавить в ваш цикл строку типа $ a = 1..23; ', чтобы показать, что изменения не отражены в исполнении промежуточного цикла. – ruffin

+1

Пункт № 2 неверен (по крайней мере, с v5 с массивом фиксированного размера). Вы можете изменить массив и увидеть его внутри конструкции 'ForEach'. Если бы вы добавили '$ a [1] = 9' в конструкцию' ForEach', он отобразит 9 как 2-й элемент, но вы не сможете добавлять/удалять элементы из массива и все, что вы добавляете, используя '+ = 'оператор не будет отображаться до конца. Если не массив фиксированного размера (т. Е. '$ A = [System.Collections.ArrayList] @ (1,2,3)'), то любая попытка изменить содержимое вызовет изменение коллекции; операция перечисления может не выполняться. Ошибка, завершающая цикл. – Adrian

+1

Это совершенно неверный ответ. Вопрос в том, что касается «Foreach-Object». В powershell (главным образом раздражающий gotcha btw) 'foreach' является« оператором »и« псевдонимом ». 'foreach', предоставленный в этом ответе плавкой, является« оператором », а не« псевдонимом ». См. [Здесь.] (Https://blogs.technet.microsoft.com/heyscriptingguy/2014/07/08/getting-to-know-foreach-and-foreach-object/) Примечание: этот ответ представляет собой полный рефакторинг кода и может не работать во многих ситуациях. –

6

Чтобы остановить трубопровод, из которого ForEach-Object является частью, просто используйте инструкцию continue внутри блока сценария под ForEach-Object. continue ведет себя по-другому, когда вы используете его в foreach(...) {...} и в ForEach-Object {...}, и вот почему это возможно. Если вы хотите продолжать создавать объекты в трубопроводе, отбрасывая некоторые из исходных объектов, лучший способ сделать это - отфильтровать с помощью Where-Object.

+0

+1. Интересно. Я этого никогда не знал. Кажется, что это работает одинаково, если вы используете 'break' или' continue'. Интересно, почему это не сработало для автора вопроса, так как они сказали, что попробовали оба. – BACON

+0

Любая идея, где это задокументировано? ['about_break'] (https://docs.microsoft.com/powershell/module/microsoft.powershell.core/about/about_break) и [' about_continue'] (https://docs.microsoft.com/powershell/module /microsoft.powershell.core/about/about_continue) говорят только о операторах 'for',' foreach', 'while' и' switch'. ['ForEach-Object'] (https://docs.microsoft.com/powershell/module/microsoft.powershell.core/foreach-object) не упоминает' break' или 'continue'. – BACON

+0

Это не работает для меня - я получаю исключение Continue на 'Get-ADGroupMember' – PeterX

-1

Для «продолжения» внутри трубопровода ForEach-Object просто используйте return. Он делает то, что вы ожидали бы continue: пропустил остальную часть блока и продолжил следующую итерацию.

+0

Мне нужно выйти из цикла - я получаю исключения с break и continue ... и return просто продолжает обработку для' Get-ADGroupMember' – PeterX