Переменный обзор в 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

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

62
задан 10 January 2015 в 03:32

4 ответа

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

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

  • global раньше получал доступ/изменял в наиболее удаленном объеме (например, интерактивная оболочка)
  • script используемый на получают доступ/изменяют в объеме под управлением сценария (.ps1 файл). Не запущение скрипта затем действует в качестве global.

(Для -Scope параметр *-Variable cmdlets видят справку.)

, Например, в Вашем втором примере, для прямого изменения глобального $array:

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

для получения дополнительной информации посмотрите тему справки about_scopes.

71
ответ дан 31 October 2019 в 13:21

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 $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$: тест всегда будет $null.

85
ответ дан 31 October 2019 в 13:21

Не просто varibles. Когда это говорит "объект", это означает переменные, функции, псевдонимы и psdrives. У всех тех есть объем.

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. Добавление к тому массиву на самом деле уничтожает исходный массив и создает новый. Так как это было создано в том объеме, это уничтожается, когда от выходов функционального блока или блока сценария и объема избавляются.

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

16
ответ дан 31 October 2019 в 13:21

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

([ref]$var).value = 'x'

Это изменяет значение $var независимо от того, что определяет объем его, оказывается, находится в. Вы не должны знать его объем; только то, что это действительно на самом деле уже существует. Использовать пример OP:

$array=@("g")
function foo()
{
    ([ref]$array).Value += "h"
    Write-Host $array
}
& {
    ([ref]$array).Value +="s"
    Write-Host $array
}
foo
Write-Host $array

Производит:

g s
g s h
g s h

Объяснение:
([касательно] $var) получает Вас указатель на переменную. Так как это - операция чтения, которую это разрешает к новому объему, который на самом деле создавал то имя. Это также объясняет ошибку, если переменная не существует, потому что [касательно] ничего не может создать, это может только возвратить ссылку на что-то, что уже существует.

.value затем берет Вас к имущественным ценностям определение переменной; который можно затем установить.

можно испытать желание сделать что-то вроде этого, потому что иногда похоже, что это работает.

([ref]$var) = "New Value"

не ДЕЛАЮТ!!!!
экземпляры, где это похоже на него, работают, иллюзия, потому что PowerShell делает что-то, что это только делает при некоторых очень узких обстоятельствах такой как на командной строке. Вы не можете рассчитывать на него. На самом деле это не работает в примере OP.

1
ответ дан 31 October 2019 в 13:21

Другие вопросы по тегам:

Похожие вопросы: