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一个新对象,它会修改父作用域中的对象。