about_Pipeline_Chain_Operators
Kısa açıklama
PowerShell'de ve ||
işleçleriyle &&
zincirleme işlem hatlarını açıklar.
Uzun açıklama
PowerShell 7'de başlayarak PowerShell, işlem hatlarını &&
koşullu olarak zincirleme amacıyla ve ||
işleçlerini uygular. Bu işleçler PowerShell'de işlem hattı zinciri işleçleri olarak bilinir ve bash, zsh ve sh gibi POSIX kabuklarındaki AND-OR listelerinin yanı sıra Windows Komut Kabuğu'ndaki (cmd.exe) koşullu işleme simgelerine benzer.
İşleç &&
, sol işlem hattı başarılı olursa sağ işlem hattını yürütür. Buna karşılık, ||
sol işlem hattı başarısız olursa işleç sağ işlem hattını yürütür.
Bu işleçler, işlem hattının $?
başarısız olup olmadığını belirlemek için ve $LASTEXITCODE
değişkenlerini kullanır. Bu, bunları yalnızca cmdlet'ler veya işlevlerle değil yerel komutlarla kullanmanıza olanak tanır. Örneğin:
# 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
Örnekler
İki başarılı komut
Write-Output 'First' && Write-Output 'Second'
First
Second
İlk komut başarısız olur ve ikincinin yürütülememesine neden olur
Write-Error 'Bad' && Write-Output 'Second'
Write-Error: Bad
İlk komut başarılı olur, bu nedenle ikinci komut yürütülmez
Write-Output 'First' || Write-Output 'Second'
First
İlk komut başarısız olduğundan ikinci komut yürütülür
Write-Error 'Bad' || Write-Output 'Second'
Write-Error: Bad
Second
İşlem hattı başarısı, PowerShell'in $?
yürütme durumuna göre bir işlem hattı yürüttükten sonra otomatik olarak ayarladığı değişkenin değeriyle tanımlanır.
Bu, işlem hattı zinciri işleçlerinin aşağıdaki eşdeğerliğe sahip olduğu anlamına gelir:
Test-Command '1' && Test-Command '2'
ile aynı şekilde çalışır
Test-Command '1'; if ($?) { Test-Command '2' }
ve
Test-Command '1' || Test-Command '2'
ile aynı şekilde çalışır
Test-Command '1'; if (-not $?) { Test-Command '2' }
İşlem hattı zincirlerinden atama
bir işlem hattı zincirinden değişken atamak, zincirdeki tüm işlem hatlarının birleştirmesini alır:
$result = Write-Output '1' && Write-Output '2'
$result
1
2
İşlem hattı zincirinden atama sırasında bir betik sonlandırma hatası oluşursa atama başarılı olmaz:
try
{
$result = Write-Output 'Value' && $(throw 'Bad')
}
catch
{
# Do nothing, just squash the error
}
"Result: $result"
Result:
İşleç söz dizimi ve öncelik
Diğer işleçlerden &&
farklı olarak veya ||
gibi +
-and
ifadeler yerine işlem hatlarında çalışır.
&&
ve ||
iş işleçlerinden (), atamadan=
(|
) veya>
noktalı virgülden;
(&
) daha düşük önceliğe sahiptir. Bu, işlem hattı zincirindeki işlem hatlarının tek tek yeniden yönlendirilebileceği ve işlem hattı zincirlerinin tamamının arka planlı olarak, değişkenlere atanabileceği veya deyim olarak ayrılabileceği anlamına gelir.
İşlem hattı zincirinde daha düşük öncelik söz dizimi kullanmak için parantez (...)
kullanımını göz önünde bulundurun. Benzer şekilde, bir deyimi bir işlem hattı zincirine eklemek için bir alt ifade $(...)
kullanılabilir. Bu, yerel komutları denetim akışıyla birleştirmek için yararlı olabilir:
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'de bu söz dizimlerinin davranışı, bir komut parantez veya alt ifade içinde başarılı olduğunda veya başarısız olduğunda beklendiği gibi ayarlı olacak şekilde değiştirilmiştir $?
.
PowerShell'deki &&
diğer işleçlerin çoğu gibi ve ||
aynı zamanda soldan ilişkilendirilir, yani soldan gruplandırılır. Örneğin:
Get-ChildItem -Path ./file.txt ||
Write-Error "file.txt doesn't exist" &&
Get-Content -Raw ./file.txt
şu şekilde gruplandırılır:
(Get-ChildItem -Path ./file.txt || Write-Error "file.txt doesn't exist") &&
Get-Content -Raw ./file.txt
şu değere eşdeğerdir:
Get-ChildItem -Path ./file.txt
if (-not $?) { Write-Error "file.txt does not exist" }
if ($?) { Get-Content -Raw ./file.txt }
Hata etkileşimi
İşlem hattı zinciri işleçleri hataları emmiyor. İşlem hattı zincirindeki bir deyim betik sonlandırıcı bir hata oluşturursa işlem hattı zinciri sonlandırılır.
Örneğin:
$(throw 'Bad') || Write-Output '2'
Exception: Bad
Hata yakalansa bile işlem hattı zinciri sonlandırılır:
try
{
$(throw 'Bad') || Write-Output '2'
}
catch
{
Write-Output "Caught: $_"
}
Write-Output 'Done'
Caught: Bad
Done
Bir hata sonlandırıcı değilse veya yalnızca bir işlem hattını sonlandırırsa, işlem hattı zinciri değerini $?
dikkate alan devam eder:
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
Komutlar yerine işlem hatlarını zincirleme
İşlem hattı zinciri işleçleri, yalnızca komutlar yerine işlem hatlarını zincirleme için kullanılabilir. Bu, diğer kabukların davranışıyla eşleşir, ancak başarının belirlenmesini zorlaştırabilir:
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
Sonlandırılmayan Write-Output 'All done!'
hata oluştuktan sonra başarısız olduğu varsayıldığından yürütülmediğini Test-NotTwo
unutmayın.
Ayrıca bkz.
PowerShell