PowerShell中的variables范围
PowerShell的一个令人伤心的事情是函数和脚本块是dynamic范围的。
但还有一件令我惊讶的事情是,variables在内部范围内performance为写入时拷贝(copy-on-write)。
$array=@("g") function foo() { $array += "h" Write-Host $array } & { $array +="s" Write-Host $array } foo Write-Host $array
输出是:
gs gh g
这使得dynamic范围减less了一点痛苦。 但是,如何避免写入时复制?
您可以使用范围修饰符或*-Variable
cmdlet。
范围修饰符是:
-
global
用于访问/修改最外层的范围(例如交互式shell) - 用于在运行脚本(
.ps1
文件)范围内访问/修改的脚本。 如果不运行脚本,则作为global
运行。
(有关*-Variable
cmdlet的-Scope
参数,请参阅帮助。)
例如。 在你的第二个例子中,直接修改全局$array
:
& { $global:array +="s" Write-Host $array }
有关更多详细信息,请参阅帮助主题about_scopes 。
PowerShell范围文章( about_Scopes )很好,但是太冗长了,所以这是我的文章引用:
一般来说,PowerShell范围就像.NET范围一样。 他们是:
- 全球是公开的
- 脚本是内部的
- 私人是私人的
- 本地是当前的堆栈级别
- 编号范围从0..N,其中每个步骤达到堆栈级别(0是本地)
下面是一个简单的例子,它描述了作用域的用法和作用:
$test = 'Global Scope' Function Foo { $test = 'Function Scope' Write-Host $Global:test # Global Scope Write-Host $Local:test # Function Scope Write-Host (Get-Variable -Name test -ValueOnly -Scope 0) # Function Scope Write-Host (Get-Variable -Name test -ValueOnly -Scope 1) # Global Scope } Foo
正如你所看到的,你可以使用$ Global:test语法只对命名作用域,$ 0:test将总是$ null。
不只是变数。 当这个“item”表示variables,函数,别名和psdrives。 所有这些都有范围。
详细描述 Windows PowerShell保护访问variables,别名,函数和 Windows PowerShell通过限制它们可以被读取的位置来驱动(PSDrives) 改变。 通过对范围强制执行一些简单的规则,Windows PowerShell 有助于确保您不会无意中更改应该的项目 不要改变。 以下是范围的基本规则: - 您在范围中包含的项目在其范围内可见 是在任何子范围内创build的,除非你明确地做出来 私人的。 您可以放置variables,别名,函数或Windows PowerShell在一个或多个范围内驱动。 - 在范围内创build的项目只能在 它的创build范围,除非你明确指定一个 不同的范围。
您看到的写入问题副本是由于Powershell处理数组的方式。 添加到该数组实际上会破坏原始数组并创build一个新的数组。 由于它是在该范围内创build的,因此在函数或脚本块退出并处理作用域时会被销毁。
您可以在更新variables时明确地定义variables,也可以使用[ref]对象来执行更新,或者编写脚本,以便更新对象的属性或哈希表中的对象或哈希表的属性一个父范围。 这不会在本地作用域中创build一个新对象,它会修改父作用域中的对象。