Recently I discover some nasty behavior about assigning some version-like value to variable in Powershell (at least in 7.2.5).
At first I tried:
> $version = 1.2.3
> echo $version
I quickly find out that I have to escape value with quotes to make it string explicitly. This one works well:
> $version = "1.2.3"
> echo $version
1.2.3
The question is: why it works this way? Why pwsh
does not throw some kind of error in first example and just converts it to $null
? Like in other cases:
> 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.
So I believe literals like 1.2.3
are expected and managed by some rule.
I tried to dig into documentation about expressions and assignments, but can't find the correct answer.
CodePudding user response:
why it works this way?
In effect, 1.2.3
is parsed as (1.2).3
, i.e. as number literal 1.2
whose .3
property is retrieved.
Number literal 1.2
is an instance of a [double]
(System.Double
, a double-precision floating point value), and as such has no .3
property (or any other property).
By default, PowerShell quietly returns $null
when you try to access a non-existent property on an object.
As Santiago Squarzon points out, you can turn such attempts into (statement-terminating) errors if you use Set-StrictMode
-Version 2
or higher:
PS> Set-StrictMode -Version 2; 1.2.3
... The property '3' cannot be found on this object. ...
Note:
A given strict mode takes effect for the entire scope and any descendant scopes.
Note that this can make calling scripts or non-module functions fail, if they weren't designed with this strict mode in mind (it is common for code to assume that no strict mode is in effect).
To turn an active strict mode off, use
Set-StrictMode -Off
Due to a long-standing bug - see GitHub issue #2798 and #16427 - the intrinsic members
.Count
and.Length
- useful for unified handling of collections and scalars - are then not available.The fact that strict mode version 2 or higher causes a statement-terminating error for attempts to access a non-existent property means that execution continues by default, with the next statement.
- See this answer for how to make such errors script-terminating errors, i.e. fatal ones.
Finally, if you want to create 1.2.3
as a version object, you can cast from a string:
[version] '1.2.3'
to create aSystem.Version
instance.PowerShell (Core) 7 only:
[semver] '1.2.3'
to create aSystem.Management.Automation.SemanticVersion
instance.