PowerShell의 가변 범위 지정
PowerShell의 아쉬운 점은 기능과 스크립트 블록이 동적으로 범위를 지정한다는 것입니다.
하지만 저를 놀라게 한 또 다른 점은 변수가 내부 범위 내에서 복사-온-라이트(copy-on-write) 역할을 한다는 것입니다.
$array=@("g")
function foo()
{
$array += "h"
Write-Host $array
}
& {
$array +="s"
Write-Host $array
}
foo
Write-Host $array
출력은 다음과 같습니다.
g s
g h
g
그래서 역동적인 스코프가 조금 덜 고통스럽습니다.하지만 어떻게 하면 복사-온-라이트를 피할 수 있을까요?
PowerShell scope 기사(_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:test는 항상 $null입니다.
스코프 수정자를 사용하거나*-Variable
cmdlet
스코프 수정자는 다음과 같습니다.
global
셸에서 y하는 데근됨예:셸)script
중인 스됩니다().ps1
을(를) 일)로합니다. 스크립트를 실행하지 않으면 다음과 같이 작동합니다.global
.
)-Scope
*-Variable
cmdlets see help.
에서 전역 를 하려면, $array
:
& {
$global:array +="s"
Write-Host $array
}
자세한 내용은 _scope에 대한 도움말 항목을 참조하십시오.
변수만이 아닙니다.이것이 "item"이라고 말하는 것은 변수, 함수, 별칭 및 psdrive를 의미합니다.그것들은 모두 범위를 가지고 있습니다.
긴 설명Windows PowerShell은 변수, 별칭, 기능 및Windows PowerShell 드라이브(PSD)는 읽기 및 읽기 가능한 위치를 제한하여변경되었다.범위에 대한 몇 가지 간단한 규칙을 적용하여 Windows PowerShell을(를) 사용하여 실수로 변경하지 않도록 합니다.변하지 않습니다. 범위의 기본 규칙은 다음과 같습니다. - 범위에 포함하는 항목은 해당 항목이 있는 범위에 표시됩니다.명시적으로 만들지 않는 한 모든 하위 범위에서 생성되었습니다.사적인.변수, 별칭, 함수 또는 Windows를 배치할 수 있습니다.PowerShell 드라이브를 하나 이상의 범위에 배치합니다. - 범위 내에서 생성한 항목은 에서만 변경할 수 있습니다.명시적으로 지정하지 않는 한, 작성된 범위범위가 다른
지금 보시는 쓰기 문제의 복사본은 파워셸이 배열을 처리하는 방식 때문입니다.해당 배열에 추가하면 원래 배열이 실제로 파괴되고 새 배열이 생성됩니다.해당 스코프에서 생성되었기 때문에 함수 또는 스크립트 블록이 종료되고 스코프가 폐기되면 삭제됩니다.
변수를 업데이트할 때 명시적으로 범위를 지정하거나 [ref] 개체를 사용하여 업데이트하거나 스크립트를 작성하여 개체의 속성이나 개체의 해시 테이블 키 또는 상위 범위의 해시 테이블 키를 업데이트할 수 있습니다.이렇게 하면 로컬 범위에 새 개체가 생성되지 않고 상위 범위에 있는 개체가 수정됩니다.
다른 게시물들은 많은 유용한 정보를 제공하지만 RTFM으로부터 당신을 구하는 것처럼 보입니다.
언급되지 않은 답은 내가 가장 유용하다고 생각하는 것입니다!
([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
설명:
([ref]$var)는 변수에 대한 포인터를 가져옵니다.읽기 작업이므로 실제로 해당 이름을 만든 가장 최근의 범위로 해결됩니다.또한 [ref]가 아무것도 생성할 수 없기 때문에 변수가 존재하지 않는 경우에는 이미 존재하는 것에 대한 참조만 반환할 수 있습니다.
그런 다음 .value를 선택하면 변수의 정의를 저장하는 속성으로 이동합니다. 그런 다음 변수 정의를 설정할 수 있습니다.
때로는 효과가 있는 것처럼 보이기 때문에 여러분은 이와 같은 일을 하고 싶은 유혹을 받을 수도 있습니다.
([ref]$var) = "New Value"
하지마!!!!
PowerShell이 명령줄과 같은 매우 좁은 환경에서만 수행하는 작업이기 때문에 작동하는 것처럼 보이는 경우는 환상에 불과합니다.믿을 수 없습니다.사실 OP 예제에서는 작동하지 않습니다.
PowerShell의 아쉬운 점은 기능과 스크립트 블록이 동적으로 범위를 지정한다는 것입니다.
.GetNewClosure()를 사용하여 즉시 로컬 범위에서 변수를 캡처하는 클로저를 만듭니다.
function New-Closure
{
$foo = 42
{$foo}.GetNewClosure()
}
❯ $Closure = New-Closure
❯ & $Closure
# output: 42
스코프는 다음 모듈 속성을 통해 액세스할 수 있습니다.
❯ {"some new scriptblock"}.Module
# no output
❯ $Closure.Module
ModuleType Version PreRelease Name ExportedCommands
---------- ------- ---------- ---- ----------------
Script 0.0 __DynamicModule_f89a39f6-f9f7-40ce…
함수도 동적 범위가 되어야 하는지 여부는 언어 설계 결정입니다.함수가 호출자의 범위에서 동적 변수에 액세스할 수 없도록 허용하는 스크립트 언어를 생각할 수 없습니다. - 아마도 당신은 Haskell ;-)에서 자랐을 것입니다.
편집: 함수는 포함된 모듈의 범위에 접근할 수 있습니다.파워셸 전개 단위는 모듈입니다.모듈을 작성하지 않으려면 동적 모듈을 생성할 수 있습니다.
New-Module {
$foo = 23
function Get-EnclosedFoo
{
$foo
}
}
# output: dynamic module
Get-EnclosedFoo
# output: 23
언급URL : https://stackoverflow.com/questions/9325569/variable-scoping-in-powershell
'programing' 카테고리의 다른 글
어떻게 하면 유튜브 비디오의 음소거를 해제하고 자동 재생을 해제할 수 있습니까? (0) | 2023.09.25 |
---|---|
프로젝트에 새 글꼴을 가져오는 방법 - Angular 5 (0) | 2023.09.25 |
modf()를 사용하지 않고 플로트의 분수 부분 가져오기 (0) | 2023.09.25 |
두 데이터베이스의 구조를 비교하시겠습니까? (0) | 2023.09.25 |
Python 프로젝트에서 Google API를 사용하도록 GOOGLE_APPLICATION_CREEDENCALES 설정 (0) | 2023.09.20 |