我想使用以下代码测试别名是否存在:
if( (get-alias ls) ) {
echo "=> Alias ls already exists."
} else {
echo "=> Alias ls does not exist."
}
运行时,它显示:
CommandType Name Version Source
----------- ---- ------- ------
Alias ls -> Get-ChildItem
=> Alias ls already exits.
我试图将命令的输出重定向到 $null :
if( (get-alias ls >$null) ) {
echo "=> Alias ls already exits."
} else {
echo "=> Alias ls does not exist."
}
我预计运行时会出现以下输出:
=> Alias ls already exists.
但代码片段的结果不知何故发生了改变:
=> Alias ls does not exist.
如果我在第一组括号后重定向,我也会得到:
=> Alias ls does not exist.
为什么重定向会干扰结果?
If
测试是否有输出,而不是$?
命令的结果代码。你可以用 组合两个语句$( )
。因为通过将成功流(又名 stdOut)重定向到
$null
无需评估的任何内容if
,从而导致$false
检测。你可以使用
这种方式
If
将评估是否有任何非假值存储到关联变量中,在这种情况下$null
,它会被立即丢弃Get-Alias
在一个不存在的别名上使用会抛出一个不停止的错误并返回一个$null
。-ErrorAction SilentlyContinue
会隐藏错误(同时仍将其记录到$Error
),并且因为一个$null
值已经存储,if
会检测到$false
当然,如果
Get-Alias
返回一个值,if
将会检测$true
并且因为该值存储到$null
其中将会被立即销毁。添加到现有的有用答案:
确实 -与 POSIX 兼容的 shell 不同
bash
- PowerShell 条件作用于被测试命令的成功流 输出,而不是其成功状态(反映在自动$?
变量中)。[1]如果输出还不是布尔值(
$true
或$false
),则使用about_Booleans帮助主题中描述的规则将其强制转换为。例如,一个没有产生输出的命令被解释为
$false
- 这可能与该命令通过反映发出错误情况信号有关,也可能无关。$?
$false
然而,在PowerShell (Core) 7(跨平台的按需安装版本)中,有一些条件形式作用于
$?
,即成功状态,就像在 POSIX 兼容 shell 中一样,该功能借用自它,即&&
和||
管道链运算符的形式 :command-a && command-b
command-b
仅当command-a
成功时才执行(如果$?
是$true
)command-a || command-b
command-b
仅当command-a
失败时执行(至少发出一个错误,在这种情况$?
下为$false
)与 POSIX-shell 类似,它们不消耗命令输出,只根据命令的成功或失败做出反应,具体如下:
$?
因此,使用表达式代替带有这些运算符的命令用途有限,因为它们通常不会导致错误,因此不会导致
$?
反映$false
;但是也有例外(但请注意,在没有错误消息的情况下try ... catch
无法抑制):1 / 0 || 'failed!'
[int]::Parse('NotANumber') || 'failed!'
然而,一个根本的限制是运算符只能链接管道,即(单个)命令和表达式,而不能链接语言语句(基于关键字),特别是包括
exit
;要做到这一点,需要使用$(...)
子表达式运算符:不起作用,因为Get-Item NoSuch || exit 1
exit
是一个语言语句。Get-Item NoSuch || $(exit 1)
作品,由于$(...)
适用于您的情况:
使用
&&
和||
:*>$null
来抑制所有流的输出,这是必要的,因为如上所述,&&
根据||
设计,不会悄悄地消耗任何输出流,即也不会悄悄地消耗成功输出流(这是常规 PowerShell 条件悄悄消耗的)。使用常规
if
语句,作为其他答案中的解决方案的替代:您可以使用调用Test-Path
来测试别名的存在,通过别名提供程序Alias:
发布的驱动器:Test-Path
只会发出$true
或$false
,因此没有错误输出需要抑制。这对于其他PowerShell 提供程序而言类似;例如,您可以用来测试函数
Test-Path Function:Foo
的存在,或者测试名为的环境变量的存在。Foo
Test-Path Env:Bar
Bar
[1] 它与 POSIX 兼容 Shell 中的同名变量相对应;不过,后者包含最近执行的命令的退出代码,而在 PowerShell 中它是一个布尔值:
$true
表示执行成功(无错误),而表示发生了(至少一个)错误。在调用外部程序$false
的上下文中,退出代码反映为,任何非零退出代码反映为。PowerShell 原生命令不使用退出代码,但 PowerShell 提供了自动变量来反映最近执行的外部程序的退出代码(以及 PowerShell 脚本(文件)的退出代码,如果它们使用数字退出)。0
$true
$?
$false
$LASTEXITCODE
*.ps1
exit