这个问题与:
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/