PoshCode / PowerShellPracticeAndStyle

The Unofficial PowerShell Best Practices and Style Guide
https://poshcode.gitbooks.io/powershell-practice-and-style
Other
2.23k stars 288 forks source link

Unquoted strings #146

Open iRon7 opened 4 years ago

iRon7 commented 4 years ago

PowerShell allows for unquoted strings as shown in the Style-Guide/Naming-Conventions:

# Instead write:
Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath README.md)

But there are limitations to using unquoted strings as e.g. spaces are not allowed in an unquoted value and will obviously fail if not quoted (with either single or double quotes, see the related issue: #63):

# Wrong:
Get-Content -Path (Join-Path -Path $PSScriptRoot -ChildPath READ ME.md)

Besides using unquoted strings in argument values, unquoted strings are common (best practice?) in hash tables keys. Hash tables are major objects in PowerShell along with PSCustomObjects which are in fact constructed from a hash table. Hash tables are also used for things like splatting and PowerShell Data files.

As with argument values, the use of unquoted hash table keys is limited to certain characters, as e.g.:

# Wrong:
$Options = @{
    Margin    = 2
    Padding   = 2
    Font-Size = 24
}

Will cause an error:

Line |
   4 |      Font-Size = 24
     |          ~
     | Missing '=' operator after key in hash literal.

In some cases there are no errors but pitfalls, like:

$Hashtable = @{ 
    U2 = 'String'
    2U = 'UInt32'
}
$Hashtable.keys
2
U2

AFAIK, there is no clear definition of when I should use quoted keys (or argument values) or when I might not. In other words: which characters are allowed for unquoted strings (or: which characters are not allowed for unquoted strings)? It is also not described in About Quoting Rules or in About Special Characters (Assuming I am right, should I created a separate documentation issue at the PowerShell Team?)

So usually I use quotes on a trial-on-error bases or pro-actively on a better-safe-than-sorry bases. But that could cause some inconsistency in defining the best (readable) practice to resolve the above error:

$Options = @{
    Margin      = 2
    Padding     = 2
    'Font-Size' = 24
}

Or:

$Options = @{
    'Margin'    = 2
    'Padding'   = 2
    'Font-Size' = 24
}

I am especially concerned with this writing style / best practice issue because I am maintaining a ConvertTo-Expression script. Although the code might not follow the styling guidelines (yet), I am committed to follow them for the expression it outputs as much as possible. For this project, I got the issue request: Remove quotes in HashTables Keys when possible and looking for some documented guidance.

mklement0 commented 4 years ago

https://github.com/PowerShell/PowerShell/issues/6467 tries to give a comprehensive overview of the current behavior with respect to arguments in command parsing mode - however, it doesn't cover the hashtable-key issue (see below).

about_Quoting_Rules is probably the best place to document this, though it is currently being discussed in the larger context of parsing modes in https://github.com/MicrosoftDocs/PowerShell-Docs/issues/3440


As for use of unquoted key names in hash tables:

Without having looked at the source code, my understanding is as follows:


To put it in terms of guidance:

Quote your hash-table keys, if:

iRon7 commented 4 years ago

@mklement0, thank you for the comprehensive information, it is very helpful.

Jaykul commented 4 years ago

It's worth pointing out that this same advice applies whenever you're interacting with a hashtable -- even when you're calling $hashtable.Add( or getting or setting via dot notation or indexing. I.e.:

$hashtable[2u] = "UInt"
$hashtable.2u

Also worth noting is that good syntax highlighting (such as at the prompt in PSReadline) will make the distinction really obvious: image