Powershell의 범위 정보

Aug 24 2020

Powershell의 범위에 대해 배우고 있으며 몇 가지 질문이 있습니다.

  1. "로컬 범위"정보 : 내가 읽은 내용에서 로컬 범위는 항상 현재 범위입니다. 따라서 기본적으로 항목 (범위 수정 자없이), 예를 들어 변수, 일부 범위에서 스크립트 또는 전역을 만들 때 범위는 그에 따라 스크립트 / 전역이됩니다. 그래서 내 질문은 : 언제 명시 적으로 local수정자를 지정해야 할까요?
  2. MSDN 말한다 :

스크립트 또는 함수를 실행하거나 세션을 만들거나 PowerShell의 새 인스턴스를 시작하여 새 범위를 만들 수 있습니다. 새 범위를 만들면 결과는 부모 범위 (원래 범위)와 자식 범위 (만든 범위)가됩니다. ...
항목을 명시 적으로 비공개로 설정하지 않는 한 상위 범위의 항목을 하위 범위에서 사용할 수 있습니다. 그러나 항목을 만들 때 범위를 명시 적으로 지정하지 않는 한 자식 범위에서 만들고 변경하는 항목은 부모 범위에 영향을주지 않습니다.

하지만 다음을 시도 할 때 :

PS> $Name = "John" PS> Powershell.exe PS>echo $Name  // No Output

위의 인용문에서 "Powershell의 새 인스턴스 시작"은 자식 범위이므로 부모 범위의 모든 항목이 여기에 표시되어야합니다. 누군가 설명 할 수 있습니까?

답변

2 mklement0 Aug 24 2020 at 23:16

iRon의 유용한 답변 을 보완하려면 :

  1. [...] 언제 명시 적으로 지역 한정자를 지정해야합니까?

$local:범위 지정자가없는 경우 로컬 범위가 암시 되기 때문에 거의 필요 하지 않습니다 .

그러나 PowerShell의 동적 범위 지정상위 (상위) 범위의 변수 를 하위 (자식) 범위에도 표시 한다는 점을 고려 하면 참조 된 변수가 실제로 로컬 변수 로 존재하는 경우에만 적용됩니다 ( 자세한 내용 은 이 답변 참조 ).

  • 예를 들어 전역 범위 $foo = 'bar'에서 선언 한 다음 스크립트 에서 참조하면 먼저 로컬 인스턴스를 찾습니다 . 없는 경우 조상 (상위) 범위에 정의 된 (있는 경우 )이 사용되며, 이 예제에서는 전역 이되고 반환됩니다.$foo $foo$foo $foo'bar'

  • 반대로, 스크립트에서 $local:foo로컬 $foo변수를 정의 하지 않고 를 사용 하면 $null기본적으로 얻 Set-StrictMode -Version 2거나 이상이 적용되면 문 종료 오류가 발생합니다.


  1. MSDN은 다음과 같이 말합니다. [...] 세션을 만들거나 PowerShell의 새 인스턴스를 시작하여 [...] 결과는 부모 범위 (원래 범위)와 자식 범위 (사용자가 만든 범위)가됩니다.

문서 입니다 잘못 이 글을 쓰는 (A의 등이 점에서 GitHub의 문제가 제기 된) :

  • 범위 간의 조상 (상위-하위) 관계는 지정된 세션 (실행 공간) 의 컨텍스트에서만 존재합니다 .

    • 즉, 동적 범위 지정 (조상 범위의 변수 및 기타 정의의 가시성)은 지정된 세션 내의 범위에만 적용됩니다.

    • 주목할만한 예외는 기능이다 모듈에서가 않습니다 하지 호출 범위의 자식 범위에서 실행 - (가) 범위를 호출하면 될 일이 있다는 경우를 제외하고 글로벌 범위; 모듈에는 전역 범위에만 연결된 자체 범위 도메인 (기술적으로 세션 상태 라고 함 ) 이 있습니다 . 토론 은 이 GitHub 문서 문제 를 참조 하세요 .

  • 따라서, 어떤 아이 범위 호출 범위는 다음과 같은 경우에 생성되지 않습니다 새로 시작 코드가 호출 범위에서 변수 (및 기타 정의)의 아무것도 알고 :

    • PowerShell 원격을 통해 새 세션 시작 (예 :) Enter-PSSession또는Invoke-Command -Computer

    • 시작 배경 [스레드] 작업 과를 Start-Job하거나 Start-ThreadJob또는 병렬 스레드를 실행 ForEach-Object -ParallelV7.0 +에

    • 시작 새 PowerShell을 인스턴스 (프로세스) 은 Using, PowerShell을 CLI ( pwshPowerShell 용 [코어], powershell.exeWindows PowerShell을위한 참조).

    • 이러한 시나리오에서 호출 범위의 값을 새로 시작된 코드로 전달하려면 명시적인 작업이 필요합니다 .

      • CLI를 호출하거나 동일한 시스템에 Start-Job하위 프로세스 가 생성 되는를 사용하면 호출 프로세스 에 정의 된 환경 변수 만 하위 프로세스에서 자동으로 사용할 수 있게 됩니다 .
      • 그렇지 않으면 호출자의 값을 인수전달 하거나 CLI를 사용하는 경우를 제외하고 $using:범위를 통해이 답변을 참조하십시오 .
4 iRon Aug 24 2020 at 14:48

후자의 질문부터 시작합니다.

범위는 다음과 같이 함수 및 호출 된 스크립트 (cmdlet)와 함께 작동합니다.

Function Test {
    $Test++ Write-Host 'Local:' $Test
}
$Test = 5 Test Write-Host 'Global:' $Test

보고:

Local: 6
Global: 5

과:

Function Test {
    $Global:Test++ Write-Host 'Local:' $Test
}
$Test = 5 Test Write-Host 'Global:' $Test

보고:

Local: 6
Global: 6

또는 스크립트에 함수를 넣는 경우 (예 :) MyScript.ps1:

$Test = 5 .\MyScript.ps1 Write-Host $Test # $Test is unaffected unless you use the $Global scope in your script

현재 범위에서 실행될 스크립트 를 Dot-Source 하지 않는 한 기본적으로 위와 동일한 결과를 반환 합니다.

$Test = 5 . .\MyScript.ps1 Write-Host $Test # $Test might be affected by MyScript.ps1 if you just use $Test

수행중인 작업 :
새로운 Powershell.exe변수 목록으로 시작 하는 완전한 새 PowerShell 세션 (사용 )을 만들고 있습니다. 새 세션에서 가져온
경우 초기 변수가 다시 표시됩니다 exit.

PS C:\> $Name = "John" PS C:\> Powershell.exe Windows PowerShell Copyright (C) Microsoft Corporation. All rights reserved. Try the new cross-platform PowerShell https://aka.ms/pscore6 PS C:\> Write-Host 'New session' $Name
New session
PS C:\> Exit
PS C:\> Write-Host 'Initial session' $Name
Initial session John

첫 번째 질문과 관련하여 명시 적으로 $Local범위를 참조해야하는 응용 프로그램이 많지 않지만 사용할 수있는 예를 제공하기 위해 다음과 같이 생각합니다.

$Test = 5 Function Test { Write-Host ($Local:Test++)
}
Test

위의 예에서 단항 증가 연산자 는 0명시 적으로 $Local범위를 사용하는 경우 (실제로 캐스트 될 빈 지역 변수로 시작 0)와 변수 의 복사본을 상속 할 범위 5를 생략하는 경우로 시작합니다. 부모 범위.$Local$Test