What type of object is $: (such as `$code:`) in Powershell?

后端 未结 2 1021
小蘑菇
小蘑菇 2020-11-27 22:59

I was using tab autocompletion for a variable name in Powershell 5.1 today and noticed that one of the choices was the name of a PSDrive. The drive name is docs

相关标签:
2条回答
  • 2020-11-27 23:11

    What you're seeing is namespace variable notation, which is a variable-based way to access the content of items in PowerShell drives whose underlying provider implements content-based access (i.e., implements the IContentCmdletProvider interface).

    The general syntax is:

    ${<drive>:<path>}       # same as: Get-Content <drive>:<path>
    
    ${<drive>:<path>} = ... # same as: Set-Content <drive>:<path> -Value ...
    

    The enclosing {...} aren't necessary if both the <drive> name and the <path> can syntactically serve as a variable name; e.g.:

    $env:HOME  # no {...} needed
    
    ${env:ProgramFiles(x86)} # {...} needed due to "(" and ")"
    

    In practice, as of Windows PowerShell v5.1, the following in-box drive providers support namespace variable notation:

    • Environment (drive Env:)
    • Function (drive Function:)
    • Alias (drive Alias:)
    • FileSystem (drives C:, ...)
    • Variable (drive Variable:) - though virtually pointless, given that omitting the drive part accesses variables by default (e.g., $variable:HOME is the same as just $HOME).

    Of these, the Env: drive is by far the most frequently used with namespace variable notation, even though most users aren't aware of what underlies an environment-variable references such as $env:HOME.

    On occasion you see it used with a filesystem drive - e.g., ${c:\foo\file.txt} - but the fact that you can only use literal paths and that you cannot control the character encoding limits its usefulness.

    It allows interesting uses, however; e.g.:

    PS> $alias:foreach  # Get the definition of alias 'foreach'
    ForEach-Object
    
    PS> $function:prompt # Get the body of the 'prompt' function
    "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) ";
    # .Link
    # https://go.microsoft.com/fwlink/?LinkID=225750
    # .ExternalHelp System.Management.Automation.dll-help.xml
    
    # Define a function foo that echoes 'hi' and invoke it.
    PS> $function:foo = { 'hi' }; foo
    hi
    

    Note:

    • Because ${<drive>:<path>} and ${<drive>:<path>} = <value> are equivalent to
      Get-Content -Path <drive>:<path> and Set-Content -Path <drive>:<path> <value>, paths are interpreted as wildcard expressions (because that's what -Path does, as opposed to -LiteralPath), which can cause problems with paths that look like wildcards - see this answer for an example and a workaround.

    • As of this writing, namespace variable notation isn't officially documented yet, but this GitHub issue suggests doing so.

    0 讨论(0)
  • 2020-11-27 23:23

    $env is the Windows environment variables, the same as what you get when you do SET in a command prompt. There are a few that are PS-specific.

    The variable is providing access to the Environment Provider. https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables?view=powershell-6

    There are a bunch of other Providers that are described here: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_providers?view=powershell-6

    As it says in the doco:

    The model for data presentation is a file system drive. To use data that the provider exposes, you view it, move through it, and change it as though it were data on a hard drive. Therefore, the most important information about a provider is the name of the drive that it supports.

    0 讨论(0)
提交回复
热议问题