web-dev-qa-db-ja.com

PowerShell関数を終了しますが、スクリプトを続行します

これは非常に馬鹿げた質問のように思えるかもしれませんが、私は本当にそれを理解することはできません。関数が最初のヒット(一致)を見つけたときに停止し、残りのスクリプトを続行しようとしています。

コード:

Function Get-Foo {
    [CmdLetBinding()]
    Param ()

    1..6 | ForEach-Object {
        Write-Verbose $_
        if ($_ -eq 3) {
            Write-Output 'We found it'

            # break : Stops the execution of the function but doesn't execute the rest of the script
            # exit : Same as break
            # continue : Same as break
            # return : Executes the complete loop and the rest of the script
        }
        elseif ($_ -eq 5) {
            Write-Output 'We found it'
        }
    }
}

Get-Foo -Verbose

Write-Output 'The script continues here'

望ましい結果:

VERBOSE: 1
VERBOSE: 2
VERBOSE: 3
We found it
The script continues here

breakexitcontinue、およびreturnを使用してみましたが、これらのどれもが希望する結果を得られません。ご協力ありがとうございました。

16
DarkLite1

前述のように、Foreach-objectは独自の関数です。通常のforeachを使用

Function Get-Foo {
[CmdLetBinding()]
Param ()

$a = 1..6 
foreach($b in $a)
{
    Write-Verbose $b
    if ($b -eq 3) {
        Write-Output 'We found it'
        break
    }
    elseif ($b -eq 5) {
        Write-Output 'We found it'
    }
  }
}

Get-Foo -Verbose

Write-Output 'The script continues here'
10
Andrey Marchuk

ForEach-Objectに渡すスクリプトブロックは、それ自体が関数です。そのスクリプトブロックのreturnは、スクリプトブロックの現在の反復から単に戻ります。

すぐに戻るように将来の反復を指示するフラグが必要になります。何かのようなもの:

$done = $false;
1..6 | ForEach-Object {
  if ($done) { return; }

  if (condition) {
    # We're done!
    $done = $true;
  }
}

これよりも、Where-Objectを使用して、パイプラインオブジェクトを処理する必要があるものだけにフィルター処理する方が適切な場合があります。

1
Richard