当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 关于管道链运营商

作者:精品下载站 日期:2024-12-14 02:20:39 浏览:15 分类:玩电脑

关于管道链运营商


简短描述

描述在 PowerShell 中使用 &&|| 运算符链接管道。

详细描述

从 PowerShell 7 开始,PowerShell 实现了 &&|| 运算符来有条件地链接管道。这些运算符在 PowerShell 中称为管道链运算符,类似于 bash、zsh 和 sh 等 POSIX shell 中的 AND-OR 列表,以及 Windows Command Shell (cmd.txt) 中的条件处理符号。 EXE文件)。

如果左侧管道成功,则 && 运算符执行右侧管道。相反,如果左侧管道失败,则 || 运算符执行右侧管道。

这些运算符使用 $?$LASTEXITCODE 变量来确定管道是否失败。这允许您将它们与本机命令一起使用,而不仅仅是与 cmdlet 或函数一起使用。例如:

# 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

示例

两条成功的命令

Write-Output 'First' && Write-Output 'Second'
First
Second

第一个命令失败,导致第二个命令无法执行

Write-Error 'Bad' && Write-Output 'Second'
Write-Error: Bad

第一条命令成功,所以第二条命令不执行

Write-Output 'First' || Write-Output 'Second'
First

第一个命令失败,因此执行第二个命令

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

链接管道而不是命令

管道链运算符,顾名思义,可用于链接管道,而不仅仅是命令。这与其他 shell 的行为相匹配,但可能会使确定成功变得更加困难:

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

请注意,Write-Output 'All done!' 不会执行,因为 Test-NotTwo 在生成非终止错误后被视为失败。

参见

  • about_Automatic_Variables
  • about_Operators
  • about_管道

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯