ja-JP/about_Pipeline_Chain_Operators.help.txt
|
TOPIC about_Pipeline_Chain_Operators 簡単な説明 PowerShell でパイプラインを && 演算子と || 演算子で連結する方法に ついて説明します。 (PSHelpJaJP 日本語パッチ版) 詳細な説明 PowerShell 7 以降では、パイプラインを条件付きで連結するための && 演算子と || 演算子が実装されています。これらの演算子は PowerShell では「パイプライン連結演算子」と呼ばれ、bash、zsh、sh などの POSIX シェルにおける AND-OR リストや、Windows コマンド シェル (cmd.exe) における条件処理記号と似ています。 && 演算子は、左側のパイプラインが成功した場合に右側のパイプライン を実行します。逆に || 演算子は、左側のパイプラインが失敗した場合 に右側のパイプラインを実行します。 これらの演算子は、$? 変数と $LASTEXITCODE 変数を使ってパイプライン が失敗したかどうかを判断します。そのため、コマンドレットや関数だけ でなく、ネイティブコマンドと組み合わせて使うこともできます。 たとえば次のとおりです。 # Create an SSH key pair - if successful copy the public key to clipboard ssh-keygen -t rsa -b 2048 && Get-Content -Raw ~\.ssh\id_rsa.pub | clip 例 2 つのコマンドがどちらも成功する場合 Write-Output 'First' && Write-Output 'Second' First Second 最初のコマンドが失敗し、2 つ目が実行されない場合 Write-Error 'Bad' && Write-Output 'Second' Write-Error: Bad 最初のコマンドが成功するため、2 つ目のコマンドが実行されない 場合 Write-Output 'First' || Write-Output 'Second' First 最初のコマンドが失敗するため、2 つ目のコマンドが実行される 場合 Write-Error 'Bad' || Write-Output 'Second' Write-Error: Bad Second パイプラインの成否は $? 変数の値によって決まります。$? は、 パイプラインの実行状態に基づいて、パイプラインの実行後に PowerShell が自動的に設定します。つまり、パイプライン連結演算子には次のような 等価性があります。 Test-Command '1' && Test-Command '2' は、次と同じ動作になります。 Test-Command '1'; if ($?) { Test-Command '2' } また、 Test-Command '1' || Test-Command '2' は、次と同じ動作になります。 Test-Command '1'; if (-not $?) { Test-Command '2' } パイプライン連結からの代入 パイプライン連結から変数に代入すると、連結内のすべての パイプラインを連結した結果が代入されます。 $result = Write-Output '1' && Write-Output '2' $result 1 2 パイプライン連結からの代入中にスクリプトを終了させるエラーが 発生した場合、代入は成功しません。 try { $result = Write-Output 'Value' && $(throw 'Bad') } catch { # Do nothing, just squash the error } "Result: $result" Result: 演算子の構文と優先順位 他の演算子とは異なり、&& と || は、たとえば + や -and のような 式ではなく、パイプラインを対象に動作します。 && と || は、パイプ (|) やリダイレクト (>) より優先順位が低い 一方で、ジョブ演算子 (&)、代入 (=)、セミコロン (;) よりは 優先順位が高くなります。つまり、パイプライン連結内の各 パイプラインを個別にリダイレクトでき、パイプライン連結全体を バックグラウンドで実行したり、変数に代入したり、ステートメント として区切ったりできます。 パイプライン連結内で優先順位の低い構文を使うには、丸括弧 (...) の使用を検討してください。同様に、パイプライン連結内に ステートメントを埋め込むには、サブ式 $(...) を使用できます。 これは、ネイティブコマンドを制御フローと組み合わせる場合に 役立ちます。 foreach ($file in 'file1','file2','file3') { # When find succeeds, the loop breaks find $file && Write-Output "Found $file" && $(break) } find: file1: No such file or directory file2 Found file2 PowerShell 7 では、これらの構文の動作が変更され、丸括弧内や サブ式内でコマンドが成功または失敗したときに、$? が期待どおり に設定されるようになりました。 PowerShell の他のほとんどの演算子と同様に、&& と || も 「左結合」であり、左からグループ化されます。たとえば次の とおりです。 Get-ChildItem -Path ./file.txt || Write-Error "file.txt doesn't exist" && Get-Content -Raw ./file.txt これは次のようにグループ化されます。 (Get-ChildItem -Path ./file.txt || Write-Error "file.txt doesn't exist") && Get-Content -Raw ./file.txt これは次と等価です。 Get-ChildItem -Path ./file.txt if (-not $?) { Write-Error "file.txt does not exist" } if ($?) { Get-Content -Raw ./file.txt } エラーとの相互作用 パイプライン連結演算子はエラーを吸収しません。パイプライン連結 内のステートメントがスクリプトを終了させるエラーをスローすると、 パイプライン連結は終了します。 たとえば次のとおりです。 $(throw 'Bad') || Write-Output '2' Exception: Bad エラーがキャッチされた場合でも、パイプライン連結は終了します。 try { $(throw 'Bad') || Write-Output '2' } catch { Write-Output "Caught: $_" } Write-Output 'Done' Caught: Bad Done エラーが非終了エラーであるか、パイプラインのみを終了させる ものである場合、パイプライン連結は $? の値を尊重して継続 します。 function Test-NonTerminatingError { [CmdletBinding()] param() $exception = [System.Exception]::new('BAD') $errorId = 'BAD' $errorCategory = 'NotSpecified' $errorRecord = [System.Management.Automation.ErrorRecord]::new( $exception, $errorId, $errorCategory, $null ) $PSCmdlet.WriteError($errorRecord) } Test-NonTerminatingError || Write-Output 'Second' Test-NonTerminatingError: BAD Second コマンドではなくパイプラインを連結する パイプライン連結演算子は、その名前のとおり、単にコマンドだけ でなくパイプラインも連結できます。これは他のシェルの動作と 一致しますが、成否の判断を難しくする場合があります。 function Test-NotTwo { [CmdletBinding()] param( [Parameter(ValueFromPipeline)] $Input ) process { if ($Input -ne 2) { return $Input } $exception = [System.Exception]::new('Input is 2') $errorId = 'InputTwo' $errorCategory = 'InvalidData' $errorRecord = [System.Management.Automation.ErrorRecord]::new( $exception, $errorId, $errorCategory, $null ) $PSCmdlet.WriteError($errorRecord) } } 1,2,3 | Test-NotTwo && Write-Output 'All done!' 1 Test-NotTwo : Input is 2 3 Test-NotTwo は非終了エラーを生成した後に失敗したとみなされる ため、Write-Output 'All done!' は実行されない点に注意して ください。 関連項目 about_Automatic_Variables about_Operators about_Pipelines ---- 原文: PowerShell-Docs (CC BY 4.0) の翻訳 / PSHelpJaJP |