Переменная область видимости в PowerShell


печальная вещь о PowerShell заключается в том, что функции и скриптовые блоки динамически ограничены.

но есть еще одна вещь, которая меня удивила, это то, что переменные ведут себя как копия при записи во внутренней области.

$array=@("g")
function foo()
{
    $array += "h"
    Write-Host $array
}

& {
    $array +="s"
    Write-Host $array
}
foo

Write-Host $array

выход:

g s
g h
g

что делает динамический обзор немного менее болезненным. Но как мне избежать копирования на запись?

3 52

3 ответа:

можно использовать модификаторы области или *-Variable командлетов.

объем модификаторы:

  • global используется для доступа/изменения во внешней области (например. интерактивная оболочка)
  • script используется при доступе / изменении в области запущенного скрипта (.ps1 file). Если скрипт не запущен, то работает как global.

(для -Scope параметр *-Variable командлетов см. помощь.)

например. во втором примере, чтобы непосредственно изменить глобальный $array:

& {
  $global:array +="s"
  Write-Host $array
}

дополнительные сведения см. В разделе справки в разделе about_scopes.

статья области действия PowerShell (в разделе about_scopes) приятно, но слишком многословно, так что это цитата из моего статьи:

В общем случае области PowerShell похожи на области .NET. Они таковы:

  • глобальные общественная
  • скрипт внутренний
  • частная частный
  • Local текущий стек уровень
  • пронумерованных областей от 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 $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 like только с именованными областями, $0: test всегда будет $null.

не только varibles. При этом говорит, что "товар" это означает, переменные, функции, псевдонимы и диски. Все они имеют объем.

LONG DESCRIPTION  
    Windows PowerShell protects access to variables, aliases, functions, and
    Windows PowerShell drives (PSDrives) by limiting where they can be read and
    changed. By enforcing a few simple rules for scope, Windows PowerShell
    helps to ensure that you do not inadvertently change an item that should
    not be changed.

    The following are the basic rules of scope:

        - An item you include in a scope is visible in the scope in which it
          was created and in any child scope, unless you explicitly make it
          private. You can place variables, aliases, functions, or Windows
          PowerShell drives in one or more scopes.

        - An item that you created within a scope can be changed only in the
          scope in which it was created, unless you explicitly specify a
          different scope.

проблема копирования при записи, которую вы видите, связана с тем, как Powershell обрабатывает массивы. Добавив к этому массиву фактически уничтожает исходный массив и создает новый. Поскольку он был создан в этой области, он уничтожается при выходе функции или блока сценария и удалении области.

вы можете прямо охвата переменные при их обновлении, или вы можете использовать объекты [ref] для выполнения обновлений, или написать сценарий, чтобы вы обновляли свойство объекта или ключ хэш-таблицы объекта или хэш-таблицы в родительской области. Это не создает новый объект в локальной области, он изменяет объект в родительской области.