Печальная вещь о PowerShell состоит в том, что функциональные и блоки сценария динамично ограничены по объему.
Но существует другая вещь, которая удивила меня, то, что переменные ведут себя как копия на записи во внутреннем объеме.
$array=@("g")
function foo()
{
$array += "h"
Write-Host $array
}
& {
$array +="s"
Write-Host $array
}
foo
Write-Host $array
Вывод:
g s
g h
g
Который делает динамический обзор немного менее болезненным. Но как я избегаю копии на записи?
Можно использовать модификаторы объема или *-Variable
cmdlets.
модификаторы объема:
global
раньше получал доступ/изменял в наиболее удаленном объеме (например, интерактивная оболочка) script
используемый на получают доступ/изменяют в объеме под управлением сценария (.ps1
файл). Не запущение скрипта затем действует в качестве global
. (Для -Scope
параметр *-Variable
cmdlets видят справку.)
, Например, в Вашем втором примере, для прямого изменения глобального $array
:
& {
$global:array +="s"
Write-Host $array
}
для получения дополнительной информации посмотрите тему справки about_scopes.
PowerShell определяет объем статьи ( about_Scopes), является хорошим, но слишком подробным, таким образом, это - цитата из моего статья :
В целом, объемы PowerShell похожи на объемы.NET. Они:
Вот простой пример, который описывает использование и эффекты объемов:
$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.
Не просто 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, когда Вы обновляете их, или можно использовать [касательно] объектов сделать обновления или записать сценарий так, чтобы Вы обновили свойство объекта или ключ хеш-таблицы объекта или хеш-таблицы в родительском объеме. Это не создает новый объект в локальном объеме, он изменяет объект в родительском объеме.
В то время как другие сообщения дают большую полезную информацию, они, кажется, только сохраняют Вас от прочитайте руководство.
ответ, не упомянутый, является тем, который я нахожу самыми полезными!
([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.