Ben*_*est 5 powershell powershell-core
考虑以下哈希表:
$table = @{
6 = '10.11.12.13', '10.11.12.14'
15 = 'domain.tld'
NameServers = '10.11.12.13', '10.11.12.14'
}
Run Code Online (Sandbox Code Playgroud)
通常,当您有哈希表时,您可以引用.键名称以更加面向对象的方式使用它,而不是使用数组访问器语法[key]。例如,调用NameServers上面哈希表上的键并.返回值,我可以按预期使用该属性值的成员:
$table.NameServers # ========> 10.11.12.13
# ========> 10.11.12.14
$table.NameServers.Count # ========> 2
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试使用包含相同字符串内容的6a 访问键,它会引用正确的值,但我无法调用返回对象上的任何成员。.我必须在这里使用传统的数组访问器:
$table.6 # =====> 10.11.12.13
# =====> 10.11.12.14
$table.6.Count # =====> ParserError:
# =====> Line |
# =====> 1 | $hi.6.Count
# =====> | ~
# =====> | Missing property name after reference operator.
$table[6].Count # =====> 2
Run Code Online (Sandbox Code Playgroud)
当然,( $table.6 ).Count可以解决这个问题,但这仍然是语法的一个奇怪的怪癖,我无法解释。有趣的是,将哈希表转换为 aPSCustomObject会产生同样的问题。这可能是一个解析器错误吗?还是还有其他事情发生?
我在 Windows PowerShell 和 PowerShell 7.1 中测试了这一点,并且在两者中都会发生这种情况。
注意:这个答案最初错误地声称不起作用$table.6,因为哈希表键是整数类型的,但它工作得很好,因为“属性”访问6中的.6也被解析为整数。
正如Gyula Kokas 的有用答案所指出的那样,您在 PowerShell 的解析器中看到了有问题的行为,从 PowerShell 7.2 开始,在GitHub 问题 #14036中详细讨论了这一问题。该行为与哈希表 本身无关:
接下来的.成员访问运算符如果看起来像数字文字,例如, (a ) 甚至(!, a ),则被解析为数字。66l[long]6.0[double]
任何使用其他属性访问的尝试都会触发您看到的错误:
$foo.6.bar # !! Error "Missing property name after reference operator."
Run Code Online (Sandbox Code Playgroud)
事实上,后面以数字和字母开头的属性名称也会导致错误 - 即使6a不能解释为数字文字。
$foo.6a # !! Same error.
Run Code Online (Sandbox Code Playgroud)
顺便说一句:PowerShell 甚至允许您使用变量引用,甚至表达式(包含在 中(...))作为属性名称(例如,$propName = 'Length'; 'foo'.$propName或 ('foo'.('L' + 'ength')
解决方法:
正如您所演示的,将第一个属性访问包含在(...)-中($table.6).Count是可行的,也是如此$table.(6).Count
您还演示了$table[6].Count它适用于哈希表。
对于访问对象的实际属性,$obj.'6'.Count也可以工作(假设属性名称始终是字符串),就像使用带有字符串键的哈希表一样(例如@{ '6'= 'six' }.'6'.Length)
哈希表特定的注意事项:
为了方便语法,PowerShell 还允许使用属性访问语法 ( $obj.someProperty) 来访问哈希表的条目,在这种情况下,属性“名称”将被视为哈希表中条目的键。
访问哈希表条目的类型本机语法是$hash[$someKey]索引语法( )。
虽然属性名称(指.NET 类型的成员)始终是字符串:
也许令人惊讶的是,在定义哈希表时,不带引号的键有时会变成字符串或数字:
如果未加引号的单词可以解释为数字文字(例如,6),则它会被如此解析,并且最终会得到一个数字键;在 的情况下6,它将是[int]-typed key,因为通常的数字文字类型适用(例如,1.0将成为一个[double]键(不建议,因为二进制浮点值并不总是具有精确的十进制表示形式),并且2147483648将成为[long])。
否则(例如,NameServers),密钥将被[string]键入。
6a),则会发生错误;使用引用 ( '6a') 作为解决方法 - 请参阅GitHub 问题 #15925也就是说,即使表达式中的字符串通常需要引号,但为了方便起见,您可以在哈希表文字中定义键时省略引号 - 但识别数字文字的规则仍然适用。
显式输入哈希表键:
为了确保给定的键被解释为 a [string],请引用它(例如,'6')
通常,您还可以使用强制转换来显式键入密钥。(eg [long] 6) 或者,在数字文字中,通常的数字类型后缀字符,例如Lfor [long](eg 6L) - 请参阅此答案以了解支持的后缀的概述,其数量在 PowerShell (Core) 7+ 中显着增长。
一个基于您的哈希表的示例:
从上面可以看出,您的6键是类型(如果您希望它是string[int] ,则必须按照哈希表文字中的方式定义)。'6'
因为6in也$name.6被解析为 an ,所以查找会成功,但请注意,如果使用不同的数字类型,则查找不会成功:[int]
# !! Output is $null, because the entry key is of type [long],
# !! whereas the lookup key is [int].
@{ 6L = '[long] 6' }.6
Run Code Online (Sandbox Code Playgroud)
财产访问的具体注意事项:
通过实际的属性访问(访问 .NET 类型的本机成员),看起来像数字的名称实际上首先被解析为数字(之前必须转换为字符串),这可能会导致令人惊讶的行为:
# !! Output is $null, because the 6L after "." is parsed as a
# !! ([long]) number first, and then converted to a string, which
# !! results in "6" being used.
([pscustomobject] @{ '6L' = 'foo' }).6L
# OK - The quoting forces 6L to be a string.
([pscustomobject] @{ '6L' = 'foo' }).'6L' # -> 'foo'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1228 次 |
| 最近记录: |