我的if语句出了什么问题?

时间:2015-08-06 07:19:59

标签: powershell if-statement

一个令人困惑的问题。

$msg = 'http://www.bla.de'

$match = $msg -match '^(.*)".+?":(\S+)\s*(.*)$'
$match_linkalone = $msg -match '^(.*)(http://|https://)(\S+)\s*(.*)$'

$match
> False
$match_linkalone
> True

if($match -eq "True" -and $match_linkalone -eq "False")
    {echo 'if';}
        elseif($match_linkalone -eq "True" -and $match -eq "False")
            {echo 'elif';}
                else
                    {echo 'else';}
> else

但如果我这样做

$match = 'False'
$match_linkalone = 'True'

if($match -eq "True" -and $match_linkalone -eq "False")
    {echo 'if';}
        elseif($match_linkalone -eq "True" -and $match -eq "False")
            {echo 'elif';}
                else
                    {echo 'else';}
> elif

我真的不明白这个......

$match = False$match_linkalone = True通过-match定义时,它应该会运行到我的elseif语句中。但它会转到else,我不知道为什么......但是当我手动将文本放入两个变量时,它可以工作。

我正在使用PowerShell

2 个答案:

答案 0 :(得分:3)

您的变量$match$match_linkalone包含布尔值,但您要将它们与字符串进行比较。在比较PowerShell automatically converts之类的第二个操作数与匹配第一个操作数的类型。转换为布尔值时,空字符串变为$false,非空字符串变为$true

基本上你的表达式是这样评估的:

$match -eq "True" -and $match_linkalone -eq "False"
$false -eq $true -and $true -eq $true
$false -and $true
$false

将第二个操作数更改为布尔值:

if ($match -eq $true -and $match_linkalone -eq $false)

或(更好)完全删除比较,因为您的变量已包含布尔值:

if ($match -and -not $match_linkalone)

问题就会消失。

答案 1 :(得分:2)

首先,关于正则表达式的一些注释:

1)捕获组比非捕获组慢,因此使用例如除非您确实需要捕获群组,否则(?:.*)而不是(.*)更为理想。

2)http://|https://等于https?://。 PowerShell中也允许使用未转义的斜杠,但出于各种原因,我仍然使用\/而不是/,包括与regex101.com等工具的兼容性。

现在回答。当$foo是一个布尔值(并且-match运算符总是返回一个布尔值)时,使用像$foo -eq "True"这样的结构是个糟糕的主意。并不是因为它不会起作用(你可以通过写$foo.ToString() -eq "true"之类的东西来使它工作)但是因为它效率低,不可维护且容易出错。不要那样做!这就是你想要的:

$msg = 'http://www.bla.de'

$match = $msg -match '^(.*)".+?":(\S+)\s*(.*)$'
$match_linkalone = $msg -match '^(.*)(https?:\/\/)(\S+)\s*(.*)$'

if ( ($match) -and (! $match_linkalone) ) { 
    Write-Output 'if'
}
elseif ( ($match_linkalone) -and (! $match) ) {
    Write-Output 'elif'
}
else {
    Write-Output 'else'
}

输出:

elif