PowerShell에서 ForEach-Object를 종료하는 방법
다음 코드가 있습니다.
$project.PropertyGroup | Foreach-Object {
if($_.GetAttribute('Condition').Trim() -eq $propertyGroupConditionName.Trim()) {
$a = $project.RemoveChild($_);
Write-Host $_.GetAttribute('Condition')"has been removed.";
}
};
질문 1: ForEach-Object를 종료하려면 어떻게 해야 합니까?"break"과 "continue"를 사용하려고 했지만 작동하지 않습니다.
질문 #2: 저는 이 리스트의 변경 가능한 것을 발견했습니다.foreach
루프...C#에서는 그렇게 할 수 없어요.PowerShell에서는 왜 이런 일을 할 수 있을까요?
일단은...Foreach-Object
실제 루프가 아닌 콜링break
스크립트 뒤에 있는 문장으로 건너뛰지 않고 스크립트 전체를 취소합니다.
반대로break
그리고.continue
실제에서는 기대대로 동작합니다.foreach
고리.
항목 #1.puting a의 경우break
의 범위 내에서foreach
loop은 루프를 종료하지만 파이프라인을 정지하지는 않습니다.다음과 같은 것을 원하는 것처럼 들립니다.
$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 및 Shell)는 유사한 구성을 허용합니다.
사이에는 차이가 있다foreach
그리고.foreach-object
.
MS-ScriptingGuy에 대한 자세한 설명은 이쪽에서 확인하실 수 있습니다.
PS에서의 테스트에서는, 차이를 나타내는 스크립트를 소개합니다.
각 오브젝트:
# Omit 5.
1..10 | ForEach-Object {
if ($_ -eq 5) {return}
# if ($_ -ge 5) {return} # Omit from 5.
Write-Host $_
}
write-host "after1"
# Cancels whole script at 15, "after2" not printed.
11..20 | ForEach-Object {
if ($_ -eq 15) {continue}
Write-Host $_
}
write-host "after2"
# Cancels whole script at 25, "after3" not printed.
21..30 | ForEach-Object {
if ($_ -eq 25) {break}
Write-Host $_
}
write-host "after3"
앞지르다
# Ends foreach at 5.
foreach ($number1 in (1..10)) {
if ($number1 -eq 5) {break}
Write-Host "$number1"
}
write-host "after1"
# Omit 15.
foreach ($number2 in (11..20)) {
if ($number2 -eq 15) {continue}
Write-Host "$number2"
}
write-host "after2"
# Cancels whole script at 25, "after3" not printed.
foreach ($number3 in (21..30)) {
if ($number3 -eq 25) {return}
Write-Host "$number3"
}
write-host "after3"
파이프라인을 정지하려면ForEach-Object
부분적으로는 스테이트먼트를 사용합니다.continue
스크립트 블록 안에ForEach-Object
.continue
에서 사용하는 경우는, 동작이 다릅니다.foreach(...) {...}
및 인ForEach-Object {...}
이것이 가능한 이유입니다.파이프라인에서 오브젝트를 생성하여 원래 오브젝트의 일부를 폐기하는 경우 가장 좋은 방법은 다음 방법을 사용하여 필터링하는 것입니다.Where-Object
.
부터ForEach-Object
cmdlet입니다.break
그리고.continue
여기서는 다른 방법으로 행동할 것이다.foreach
키워드를 지정합니다.둘 다 루프를 정지하지만 스크립트 전체를 종료합니다.
브레이크:
0..3 | foreach {
if ($_ -eq 2) { break }
$_
}
echo "Never printed"
# OUTPUT:
# 0
# 1
속행:
0..3 | foreach {
if ($_ -eq 2) { continue }
$_
}
echo "Never printed"
# OUTPUT:
# 0
# 1
powershell core는 다음 방법을 사용하지만 스크립트를 깨지 않고 foreach 스크립트블록을 깨는 "좋은" 방법을 찾지 못했습니다.단, "남용" 예외는 제외합니다.
던지기:
class CustomStopUpstreamException : Exception {}
try {
0..3 | foreach {
if ($_ -eq 2) { throw [CustomStopUpstreamException]::new() }
$_
}
} catch [CustomStopUpstreamException] { }
echo "End"
# OUTPUT:
# 0
# 1
# End
(항상 가능한 것은 아니지만) 다른 방법은foreach
키워드:
포어치:
foreach ($_ in (0..3)) {
if ($_ -eq 2) { break }
$_
}
echo "End"
# OUTPUT:
# 0
# 1
# End
ForEach-Object를 계속 사용한다면 다음과 같은 "break condition"을 추가하는 것이 좋습니다.
$Break = $False;
1,2,3,4 | Where-Object { $Break -Eq $False } | ForEach-Object {
$Break = $_ -Eq 3;
Write-Host "Current number is $_";
}
위의 코드는 1, 2, 3을 출력한 후 건너뛰어야 합니다(Break before) 4.예상 출력:
Current number is 1
Current number is 2
Current number is 3
다음은 질문 #1에 대한 권장 접근법입니다.이 접근법은 ForEach-Object cmdlet을 사용하는 경우 사용합니다.EX가 아니기 때문에 질문에 직접 답변하지 않습니다.IT 파이프라인단, Q#1에서 원하는 효과를 얻을 수 있습니다.저와 같은 아마추어들이 볼 수 있는 유일한 단점은 대규모 파이프라인 반복을 처리하는 것입니다.
$zStop = $false
(97..122) | Where-Object {$zStop -eq $false} | ForEach-Object {
$zNumeric = $_
$zAlpha = [char]$zNumeric
Write-Host -ForegroundColor Yellow ("{0,4} = {1}" -f ($zNumeric, $zAlpha))
if ($zAlpha -eq "m") {$zStop = $true}
}
Write-Host -ForegroundColor Green "My PSVersion = 5.1.18362.145"
이게 도움이 됐으면 좋겠어요.모두 새해 복 많이 받으세요.
할 수 있는 .ForEach-Object
예외 없이.이것은, 보다 덜 알려진 기능을 채용하고 있습니다.Select-Object
-First
지정된 수의 파이프라인 항목이 처리되면 실제로 파이프라인이 중단됩니다.
간단한 예:
$null = 1..5 | ForEach-Object {
# Do something...
Write-Host $_
# Evaluate "break" condition -> output $true
if( $_ -eq 2 ) { $true }
} | Select-Object -First 1 # Actually breaks the pipeline
출력:
1
2
해 주세요.$null
은 은근히 은근히 은근히 .$true
이 값은 브레이크 조건에 의해 생성됩니다. 값$true
할 수 42
,"skip"
,"foobar"
만 해뭐든지 말씀해 보세요.로 뭘 좀 하면 돼Select-Object
이치노
특정 코드 블록에서 세분화된 흐름 제어를 해제하는 방법을 찾다가 이 질문을 발견했습니다.내가 결정한 해결책은 언급되지 않았다...
break 키워드를 지정한 라벨 사용
송신원: about_break
Break 문에는 내장된 루프를 종료할 수 있는 라벨을 포함할 수 있습니다.라벨은 스크립트에서 Forech, For, While 등의 임의의 루프 키워드를 지정할 수 있습니다.
여기 간단한 예가 있습니다.
: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
더 복잡한 예에서는 중첩된 레이블과 각 레이블이 구분된 결과를 보여 줍니다.
: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
코드 블록을 루프로 감싸서 다른 상황에서 동작하도록 조정할 수도 있습니다.이러한 번만 실행됩니다.
:myLabel do {
1..2 | % {
Write-Host "Iteration: $_"
break myLabel
}
} while ($false)
Write-Host "After do while loop"
# Results:
# Iteration: 1
# After do while loop
에는 두 가 있습니다.ForEach-Object
PowerShell:
- 출구 합니다.
Where-Object
물건을 .Foreach-Object
「」 - 한 경우) convert (변환)
Foreach-Object
Foreach
루핑 구조
예를 들어 보겠습니다.다음 스크립트는 두 번째 반복 후 Foreach-Object 루프에서 종료됩니다(즉, 파이프라인이 2회만 반복).
솔루션 1: 사용Where-Object
BeforeForeach-Object
:
[boolean]$exit = $false;
1..10 | Where-Object {$exit -eq $false} | Foreach-Object {
if($_ -eq 2) {$exit = $true} #OR $exit = ($_ -eq 2);
$_;
}
또는
1..10 | Where-Object {$_ -le 2} | Foreach-Object {
$_;
}
솔루션 2: 변환 완료Foreach-Object
Foreach
프프: :
Foreach ($i in 1..10) {
if ($i -eq 3) {break;}
$i;
}
PowerShell은 실제로 본체 내에서 보다 쉽게 종료 또는 분리할 수 있는 방법을 제공해야 합니다.Foreach-Object
파이프라인.주의:return
않고 .continue
는.return
:
Write-Host "Following will only skip one iteration (actually iterates all 10 times)";
1..10 | Foreach-Object {
if ($_ -eq 3) {return;} #skips only 3rd iteration.
$_;
}
HTH
질문 1에 대한 답변 - if 스테이트먼트가 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
}
};
언급URL : https://stackoverflow.com/questions/10277994/how-to-exit-from-foreach-object-in-powershell
'programing' 카테고리의 다른 글
OpenSSL: PEM 루틴:PEM_read_bio: 시작선 없음: pem_lib.c:703: 예상: 신뢰할 수 있는 증명서 (0) | 2023.04.10 |
---|---|
매크로를 사용하여 Excel 워크북의 모든 피벗 테이블 새로 고침 (0) | 2023.04.10 |
목록에서 연속된 번호 그룹 식별 (0) | 2023.04.10 |
.ps1 파일을 더블 클릭하여 PowerShell 스크립트를 실행하는 방법이 있습니까? (0) | 2023.04.10 |
jQuery .load() 호출이 로드된 HTML 파일에서 JavaScript를 실행하지 않음 (0) | 2023.04.05 |