全局和局部范围内的哈希和其他变量之间的 Powershell 差异



我注意到Powershell在本地范围内更改全局变量时管理全局变量的方式存在一些差异。特别是关联数组(哈希(看起来是本机全局的,同时其他变量类型不是全局变量,需要前缀$global:(不仅要读取值,还要更改它(。

这是我的例子:


# global variables test in powershell
$hash = @{}; # associative array
$hash["a"] = "Antenna";
$array = @(); # array
$array += "first";
$count = 1; # numeric
$glob = 1; # numeric
# here we change the values locally
function AddValues() {
$hash["b"] = "Battle";
Write-Host "local array"
$array += "second";
$array # write only "second" so is a local variable
$local = 1;
$local += 1;
Write-Host "local sum result: $local" # here the sum result is 2 ok
Write-Host "count locally: $count" # here the value is 1 ok
$count += 1;
Write-Host "count locally: $count" # here the value is still 1!!!
$count = $count+1;
Write-Host "count locally: $count" # here is 2 !!!
$global:glob += 1;
}
# call the function
AddValues
Write-Host "hash" # here the hash is ok, has 2 values 
$hash 
Write-Host "array" # here the array has only "first" !!!
$array
Write-Host "count: $count" # here the value is just 1!!!
Write-Host "global: $($global:glob)" # here the value is ok (2)

这是如何解释的?

提前谢谢你

范围规则仅适用于变量

PowerShell 的默认行为是:

  • 您可以透明地读取父作用域中的变量
  • 写入变量后,PowerShell 会创建新的本地副本

但是,当您写入哈希表中的特定键时:

$hash["b"] = "value"

。您实际上并没有向名为"hash"的变量写入任何内容 - 该变量仍然包含对完全相同的哈希表的引用(现在恰好有更多的条目(!

另一方面,如果我们实际上为$hash变量分配了一个新值,您将看到您期望的行为:

function Update-Hash {
$hash = @{"b" = "value"}
$hash
}
$hash = @{"a" = 123}
$hash   # shows the a=123 entry
Update-Hash
$hash   # still shows a=123 entry, variable is untouched

数组和属性表达式也是如此。


如果要确保获得的变量引用确实是局部的(并且不打算修改父作用域中的对象(,请使用local作用域修饰符:

function f
{
if($false){
# Oops
$hash = @{}
}
# This will affect any $hash variable in the callers scope
$hash['key'] = 'value'
# This will, appropriately, throw an index exception
$local:hash['key'] = 'value'
}

作为Mathias R. Jessen出色回答的例证:

$hash = @{}; # associative array
$hash["a"] = "Antenna";
$array  = @(); # array
$array += "first";
$count  = 1000; # numeric
$glob   = 2000; # numeric
# here we change the values locally
function AddValues() {
$hash["b"] = "Battle";
$array += "second";
$local = 1;
$local += 1;
$count += 10;
$count = $count+100;
$global:glob += 2;
'---Variables inside function'
foreach ($varia in 'array','count','hash','glob','local') {
foreach ($scope in 'Local','Global','Script',0,1) {
Try {
Get-Variable $varia -scope $scope  -ErrorAction Stop |
Select-Object Name, Value, @{Name='Scope';Expression={$scope}}
} catch {}
} }
}
# call the function
AddValues
# How this is explained?
'Variables outside function'
foreach ($varia in 'array','count','hash','glob','local') {
foreach ($scope in 'Local','Global','Script',0,1) {
Try {
Get-Variable $varia -scope $scope  -ErrorAction Stop |
Select-Object Name, Value, @{Name='Scope';Expression={$scope}}
} catch {}
} }

输出显示$array局部变量在函数内创建为字符串(此行为与+=运算符有关,值得更多阐述(:

.SO61888603.ps1

---Variables inside function
Name  Value   Scope 
----  -----   ----- 
array second  Local 
array {first} Global
array {first} Script
array second  0     
array {first} 1     
count 110     Local 
count 1000    Global
count 1000    Script
count 110     0     
count 1000    1     
hash  {a, b}  Global
hash  {a, b}  Script
hash  {a, b}  1     
glob  2002    Global
glob  2002    Script
glob  2002    1     
local 2       Local 
local 2       0     
Variables outside function
array {first} Local 
array {first} Global
array {first} Script
array {first} 0     
count 1000    Local 
count 1000    Global
count 1000    Script
count 1000    0     
hash  {a, b}  Local 
hash  {a, b}  Global
hash  {a, b}  Script
hash  {a, b}  0     
glob  2002    Local 
glob  2002    Global
glob  2002    Script
glob  2002    0

最新更新