powershell - 未引用的关键规则和最佳实践

标签 powershell

这个问题与:
Unquoted tokens in argument mode involving variable references and subexpressions: why are they sometimes split into multiple arguments? .
我得到了这个 Remove quotes in HashTables Keys when possible请求我的 ConvertTo-Expression 项目。
关键是我并不完全清楚何时应该在哈希表中实际引用键。
与参数值一样,不带引号的哈希表键的使用仅限于某些字符。
不允许使用多个字符(包括空格),例如:

$Options = @{
    Margin    = 2
    Padding   = 2
    Font-Size = 24
}
会导致错误:
Line |
   4 |      Font-Size = 24
     |          ~
     | Missing '=' operator after key in hash literal.

在某些情况下,只是字符的顺序可能会导致错误甚至陷阱,例如:
$Hashtable = @{ 
    U2 = 'YouTo'
    2U = 'ToYou'
}
$Hashtable.keys
2
U2
(这是因为 U2 键将被解释为 [UInt32] 类型,这意味着 $HashTable.2U 将正确显示该值,但 $HashTable.2$HashTable.'2'$HashTable.'2U' 不会。)
除了我正在寻找一些记录在案的最佳实践的问题之外,我想安全地测试是否需要引用字符串,例如:
IsStringConstant 'Margin'    # True
IsStringConstant 'Font-Size' # False
IsStringConstant 'U2'        # True
IsStringConstant '2U'        # False
我一直在玩AST ,但这需要我构建一个 ScriptBlock第一个,即 considered unsafe .
有没有办法检查字符串是否需要为哈希表键引用?

最佳答案

I have been playing with AST, but that requires me to build a ScriptBlock first, which is considered unsafe.


这(幸运的是)不是真的 - 您可以从源代码生成 AST,而无需编译封闭的 [scriptblock]。调用 Parser.ParseInput() :
$tokens = @()
$errors = @()
$AST = [System.Management.Automation.Language.Parser]::ParseInput('U2',[ref]$tokens,[ref]$null)
在这种情况下,您实际上不需要检查 AST,您可以根据解析虚拟哈希表文字产生的 token 确定哈希表成员键是否有效:
function Test-IsValidHashtableStringLiteral
{
    param([string]$Identifier)

    $dummyTable = '@{{{0}=$()}}' -f $Identifier

    $tokens = @()
    $errors = @()
    $null = [System.Management.Automation.Language.Parser]::ParseInput($dummyTable, [ref]$tokens, [ref]$errors)

    if($errors.Count){
        # Parsing our dummy table resulted in errors, no good
        # This would be the case for `Font-Size`
        return $false
    }

    # No errors, let's ensure the member name is recognized 
    # as an identifier and not a value literal (like 2u in PowerShell >6)
    $memberName = $tokens[1]

    return $memberName.Kind -eq 'Identifier'
}
请注意 : 结果是特定于版本的 - 换句话说,如果您使用上述技术并运行 ConvertTo-Expression与您的2u例如,在 PowerShell 5.1 上,生成的表达式只能在 5.1 中正常工作 - 要生成与 7.0 兼容的表达式,您需要在 7.0 上运行它。
好消息是解析器接口(interface)自 PowerShell 3.0 以来一直保持稳定,并且语言基础架构非常向后兼容,因此这种方法适用于从 3.0 到 7.x 的所有版本

关于powershell - 未引用的关键规则和最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62754771/

相关文章:

Powershell:并行运行多个作业并查看来自后台作业的流式传输结果

arrays - 如何按每个新行拆分字符串并将每一行放入 PowerShell 中的单独数组条目中

powershell - 在 PowerShell 脚本中调用其他 PowerShell 脚本

powershell - Azure:在 DSC 扩展和 DSC 自动化之间进行选择

powershell - powershell Try/Catch/Finally 脚本的最佳实践?

powershell - 卸下断线Powershell

powershell - 脚本中的powershell语法错误 ')'

powershell - 使用添加成员将内容添加到csv

powershell - PowerShell Copy-Item 中的排除列表似乎不起作用

powershell - where-object $_ 匹配多个条件