【问题标题】:Why is my boolean of value 0 returning true?为什么我的值为 0 的布尔值返回 true?
【发布时间】:2013-09-02 04:30:53
【问题描述】:

我一直在处理一些 PowerShell 脚本,发现有些奇怪。 我有一个接受 4 个强制参数的脚本:两个字符串和两个布尔值。

.\[scriptname] [string1] [string2] [bool1] [bool2]

这很好,我已经检查过它们都被正确传递了。

但是,当 PowerShell 要求提供参数时,我发现了一些相当奇怪的情况;它将两个布尔值都设置为 true。

.\[scriptname] [string1] [string2]
please enter bool1: 0
please enter boo2: 0

然后它运行脚本,就好像 bool1 和 bool2 设置为 true,而不是我设置的那样。我对各种不同的东西都有真实的传递,它总是导致真实的。

我不确定为什么会发生这种情况,并想知道是否有人遇到过这个奇怪问题的原因或解决方案!

我还发现任务计划程序也有类似的问题。 使用

进行设置

powershell -file [scriptlocation] [string1] [string2] [bool1] [bool2]

示例:

powershell -file "C:\script1.ps1" "c:\fileOne.txt" "c:\folder1" 0 0

两个布尔值都以字符串形式出现。

【问题讨论】:

  • 请发布显示此行为的来源
  • 这与我的源代码无关,因为我所做的只是将它们作为强制参数传递。脚本的其余部分会发生什么并没有实际意义。
  • 希望您现在可以看到发布代码的好处。这样做似乎并不立即相关,但它为我们提供了关键背景,以便能够重现您的问题并更快地帮助您。 :)

标签: .net powershell parameters boolean powershell-3.0


【解决方案1】:

This blog Jeffrey Snover 提供了一些关于 Powershell 中布尔值行为的见解。下面是一段摘录,他创建了一个简单的函数“test”,根据输入参数返回真或假:

PS> test "0"
TRUE
PS> test 0
FALSE
PS> test 1
TRUE
PS> test 0.0
FALSE
PS> test 0x0
FALSE
PS> test 0mb
FALSE
PS> test 0kb
FALSE
PS> test 0D
FALSE
PS> test 0.00000001
TRUE

“0”是 TRUE,因为它是一个 STRING,长度为 1。0 是 FALSE,因为它是一个数字并且该数字为 0。在 PowerShell 中,任何 评估为 0 的数字是 FALSE,每个非零数字都是 真的。该示例向您展示了一个浮点零,一个十六进制 零,0 兆,0 公斤,0 小数,有各种各样的零,但 PowerShell,它们都评估为 FALSE。

如果没有任何示例代码,很难准确地说出发生了什么,但我们可以说的是,Powershell 不会将您的输入识别为零。也许它是一个字符串?如果您使用Read-Host 来获取用户输入,这将是正确的。这是一个例子:

PS C:\> $test = Read-Host "Input"
Input: 0
PS C:\> $test.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

PS C:\> test $test
TRUE

PS C:\> $test = [Int32]$test
PS C:\> test $test
FALSE

您可以通过使用GetType() 来检查有问题的变量,修复它可能只是显式转换为所需类型的简单问题。

我阅读你的问题的次数越多——除非我误解了它——这似乎解决了你的问题。尤其是在您评论说您一直在“传递各种不同的东西”时,因为任何非零长度字符串在这种情况下都会评估为 true。

PS C:\> $anotherTest = "42"
PS C:\> test $anotherTest
TRUE
PS C:\> $anotherTest = [Int32]$anotherTest
PS C:\> test $anotherTest
TRUE

编辑:好的,我已经对这个问题做了更多的工作,因为我知道你的环境是什么。首先,我上面告诉你的一切都是真的,所以请不要忽视它。您遇到的问题是布尔类型转换正在以一种不立即明显的方式处理 powershell 强制提示输入。

所以有些情况存在这个代码sn-p:

param
(
    [Parameter(mandatory=$true)][bool]$myBool
)
Write-Host $myBool

当你使用powershell的强制参数提示而不是在命令行提交变量时会导致如下结果:

PS C:\> .\script.ps1 
cmdlet script.ps1 at command pipeline position 1
Supply values for the following parameters: 
myBool: 0 
True

让我重申一下:在 Powershell 中,所有非空长度的字符串都计算为真。这包括“0”,这包括字符串文字。但问题是什么?我们已经明确地将我们的变量声明为bool,所以它应该明白我的意思是0,对吧?

错了。当我们将输入设置为提示时,会产生一个相当不幸的情况,即我们期望一个布尔值,或者至少是一个字符串。我们确实最终得到了 bool,但还记得当我们将非空字符串转换为 bool 时会发生什么吗?将类型转换为 bool 将应用于您在提示符处设置的文字输入,它不是数字类型。由于输入的长度为非空,因此布尔转换的计算结果为真。您实际上是在执行此操作:

PS C:\> [bool]$myBool = [bool]"0"
PS C:\> $myBool
True

这样做的最大问题是,由于我们已经将变量转换为布尔值,因此字符串已被使用,我们只剩下值 1 或 True。所以你的“0”字面上变成了1。我们不能再让0回来了。我们应该做什么?我将列出几个选项:

  • 将变量设置为[int] 类型而不是[bool]。 bool 转换消耗了“0”字符串并将其变成了 1,那么为什么不使用 不会 这样做的类型呢? Powershell 将数字 0 和 1 理解为真假,因此您可以使用任何数字类型。

输出示例:

param
(
    [Parameter(mandatory=$true)][int]$myBool
)
Write-Host $myBool

PS C:\> .\script1.ps1
cmdlet script1.ps1 at command pipeline position 1
Supply values for the following parameters:
myBool: 0
0
  • 如果您将布尔值用作逻辑开关,请考虑使用[switch] 参数类型。除非您明确设置开关,否则开关始终评估为 false。你不应该以这种方式暴露提示,所以你不会遇到这个问题。更多信息here

【讨论】:

  • 对不同类型输入的很好解释。
  • 感谢您的解释。但是,这并不能完全回答我的问题。我要问的是为什么它会从命令行中接受 0 和 1 为真和假而改变,但是当它要求命令时它会决定它们是真的?
  • 命令行和 cmdlet 的区别在于命令行足够智能,可以隐式解释您的输入——另一方面,cmdlet 具有严格的返回类型。如果我知道您使用的是什么 cmdlet,我可以进一步评论,但它看起来像 Read-Host。检查 Read-Host 上的this documentation,即使您输入数值,输出也是 System.String。您需要将该字符串显式“转换”为某种数字类型,例如 int,以便它理解您的意思是 0 而不是“0”。
  • @Hazz22 还有另一种可能性,即您没有使用 Read-Host,而是定义了一个强制参数,并简单地让它通过 powershell 的提示符......最终遇到了类似的问题作为读取主机。您最终会得到一个 string 类型的对象,因为您不再使用 powershell 的交互式控制台。在任何一种情况下,只需将您的变量转换为 [int]$value[bool]$value,您就可以使用输入。
  • 很抱歉还没有放任何代码。我一直很忙。但是你的解释是正确的!这正是我遇到的问题,并且想知道我是否会逐渐发疯!我的解决方案实际上采用了稍微不同的方式,这是通过字符串。我允许用户传入“true”、“false”、“0”或“1”,并在我创建的模块中添加了转换函数。感谢您,并将其标记为已解决!
【解决方案2】:

如果您的函数不接受布尔参数,这可能解释了为什么会发生这种情况(Hyper Anthony 解释得很好)。

那么,您的脚本是否有 param ([string]x1, [string[x2],[bool]y1,[bool]y2) 类型的声明?在这种情况下,y1 和 y2 将是布尔值,但如果不是,则可能会被视为值为 0 的字符串,在这种情况下,它会被视为不等于 0 的“0”

【讨论】:

  • 所有强制参数都已明确设置,这有点奇怪。稍后我将发布一些示例代码,以说明我的意思。
猜你喜欢
  • 1970-01-01
  • 2015-12-16
  • 1970-01-01
  • 2016-02-01
  • 2022-11-08
  • 2017-08-27
  • 2020-03-21
  • 2020-04-10
  • 2018-01-24
相关资源
最近更新 更多