首页 > 解决方案 > Solved: Strange behaviour of string comparison in Powershell

问题描述

Consider the following function :

function myfunc()
{
  if (condition1) {
    return 'nowork'
  } elseif (condition2) {
    return $false
  } elseif (condition3) {
    return $true
}

Now if I call this function, and I know that condition3 is true, I can see that True is returned:

...
$result = myfunc
Write-Host $result

(this writes True to the console.)

The next statement in the calling function is an if statement to determine what was returned, and act upon that:

$result = myfunc
Write-Host $result
if ($result -eq 'nowork') {
  do this..
} elseif ($result -eq $false) {
  do that..
} elseif ($result -eq $true) {
  do something else..
}

And this is where it gets strange (to me). Even though I can see that True is returned, the if statement decides to go do 'do this..', the first branch of the if statement, where I would have expected that 'do something else..' would have been done. Another strange thing is that it sometimes works, sometimes not. I tried changing the if statement to:

if ('nowork' -eq $result)

and then what went wrong first now worked, but later on the same issue re-appeared.

I'm guessing there's something wrong with my first string comparison, but I can't figure out what. I'm used to writing scripts in Linux (bash), so Powershell must be acting differently.

Btw: script is run in Debian 10, Powershell 7, but the exact same problem also appears on a Windows machine with Powershell 5.0.

Please help..

标签: powershell

解决方案


你在比较苹果和橘子

PowerShell 的比较运算符行为取决于左侧操作数的类型

当您的lhs ( $result) 是[bool](ie. $trueor ) 时,PowerShell 将在比较两者之前$false尝试将右侧操作数转换为 as well。[bool]

非空字符串(即'nowork')转换[bool]$true,因此if条件计算为$true -eq $true-> $true

您可以通过手动类型检查来解决此问题:

if($result -is [bool]){
  if($result){
    # was $true
  }
  else {
    # was $false
  }
}
elseif($result -eq 'nowork'){
    # was 'nowork'
}

然而,解决这个问题的更好方法是始终返回相同类型的对象。如果您有 3 种不同的退货选项,请考虑enum

enum WorkAmount
{
  None
  Some
  All
}

function myfunc()
{
  if (condition1) {
    return [WorkAmount]::None
  } elseif (condition2) {
    return [WorkAmount]::Some
  } elseif (condition3) {
    return [WorkAmount]::All
  }
}

推荐阅读