在 Powershell 中分配类似版本的值(带有两个或更多点的数字)

Dmi*_*hev 4 powershell type-conversion powershell-core

最近我发现了一些关于在 Powershell 中将一些类似版本的值分配给变量的令人讨厌的行为(至少在 7.2.5 中)。

起初我尝试过:

> $version = 1.2.3
> echo $version

Run Code Online (Sandbox Code Playgroud)

我很快发现我必须用引号转义 thr 值才能显式地使其成为字符串。这个效果很好:

> $version = "1.2.3"
> echo $version
1.2.3
Run Code Online (Sandbox Code Playgroud)

问题是:为什么会这样?为什么pwsh在第一个示例中不抛出某种错误而只是将其转换为$null?就像其他情况一样:

> 12a
12a: The term '12a' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

> [int]12a
ParserError:
Line |
   1 |  [int]12a
     |       ~~~
     | Unexpected token '12a' in expression or statement.
Run Code Online (Sandbox Code Playgroud)

所以我相信像这样的文字1.2.3 由某种规则所期望和管理的。我试图深入研究有关表达式赋值的文档,但找不到正确的答案。

mkl*_*nt0 6

为什么会这样?

实际上,1.2.3被解析为(1.2).3,即作为其属性被检索的数字文字。 1.2.3

数字文字是( ,双精度浮点值)1.2的实例,因此没有属性(或任何其他属性)。[double]System.Double .3

$null默认情况下,当您尝试访问对象上不存在的属性时,PowerShell 会悄悄返回。

正如Santiago Squarzon指出的,如果您使用或更高版本,您可以将此类尝试转变为(语句终止)错误Set-StrictMode -Version 2

PS> Set-StrictMode -Version 2; 1.2.3
... The property '3' cannot be found on this object. ...
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 给定的严格模式对整个作用域和任何后代作用域生效。

    • 请注意,如果脚本或非模块函数在设计时没有考虑到这种严格模式,这可能会使调用脚本或非模块函数失败(代码通常假设没有严格模式生效)。

    • 要关闭活动的严格模式,请使用Set-StrictMode -Off

  • 由于长期存在的错误 - 请参阅GitHub 问题 #2798#16427 -内部成员 .Count.Length- 对于统一处理集合和标量有用 - 然后不可用。

  • 事实上,严格模式版本 2 或更高版本会因尝试访问不存在的属性而导致语句终止错误,这意味着默认情况下会继续执行下一条语句。

    • 有关如何使此类错误成为脚本终止错误(即致命错误)的信息,请参阅此答案
  • 请参阅下面iRon的评论,获取 GitHub 问题的链接,这些问题讨论了手头可能令人惊讶的行为(1.2.3悄悄地评估为$null),以及实现PSScriptAnalyzer规则的建议的链接,该规则将警告诸如 之类的表达式1.2.3,以便您例如,在 Visual Studio Code 中编辑代码时收到设计时警告。


最后,如果您想创建1.2.3版本对象,您可以从字符串进行转换: