Home > database >  Assignment of version-like value (numbers with two or more dots) in Powershell
Assignment of version-like value (numbers with two or more dots) in Powershell

Time:07-05

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:

  • Related