Powershell 中的 $<drivename>:(例如 `$code:`)是什么类型的对象?

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

我今天在 Powershell 5.1 中对变量名称使用制表符自动完成,并注意到其中一个选项是 PS 驱动器的名称。驱动器名称是 docs,我想扩展的名称是 $document_name。当我输入 $do<tab> 时,shell 确实将我输入的内容扩展为 $document_name,但出于某种原因,我第二次输入 <tab>,这时扩展文本发生了变化至 $docs:.

我进一步探索,发现我的每个 PS 驱动器都存在这种类型的变量,或者至少选项卡扩展表明它存在。

更正式地说,对于每个 PSDrive PSD,选项卡扩展认为 $PSD: 是有效的。

我的问题很简单:这些到底是什么?以下是我到目前为止所做的一些观察:

获取文件的内容。

λ  ${code:\readme.txt}
Hello, world!

只是为了证明上面结果的类型是String:

λ  ${code:\readme.txt} | % { $_.GetType().Name }
String

尝试将其用作对 PS 驱动器的引用对于许多操作来说效果不佳,例如 cd:

C:\
λ  cd ${code:}
At line:1 char:4
+ cd ${code:}
+    ~~~~~~~~
Variable reference is not valid. The variable name is missing.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : InvalidBracedVariableReference

我可以继续,但我被难住了。如果我将 $code:(或 $env:,就此而言)传递给 Get-Member,我会收到一条错误消息 Variable reference is not valid

那么 "variables" 和 $env$<PSDrive>:(例如 $code:)到底是什么?它们是表达式吗?内置表达式?某种物体?谢谢你的帮助。

$env 是 Windows 环境变量,与在命令提示符下执行 SET 时得到的相同。有一些是 PS 特定的。

该变量正在提供对环境提供程序的访问。 https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables?view=powershell-6

这里描述了很多其他提供程序:https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_providers?view=powershell-6

正如文档中所说:

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.

您看到的是命名空间变量表示法,这是一种基于变量的方式来访问PowerShell 驱动器 中项目的内容,其底层提供程序实现了基于内容的访问(即实现了 IContentCmdletProvider 接口)。

一般语法是:

${<drive>:<path>}       # same as: Get-Content <drive>:<path>

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

如果 <drive> 名称和 <path> 在语法上都可以用作变量名称,则不需要封闭的 {...};例如:

$env:HOME  # no {...} needed

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

实际上,从 Windows PowerShell v5.1 开始,以下内置驱动器提供程序支持命名空间变量表示法

  • 环境(驱动器 Env:
  • 函数(驱动器Function:
  • 别名(驱动器 Alias:
  • 文件系统(驱动器 C:,...)
  • Variable (drive Variable:) - 虽然实际上没有意义,因为省略驱动部分默认访问变量(例如,$variable:HOME$HOME 相同)。

其中,Env: 驱动器是迄今为止最常与名称空间变量符号一起使用的驱动器,尽管大多数用户并不知道 $env:HOME 等环境变量引用的基础是什么.

有时您会看到它与文件系统驱动器一起使用 - 例如 ${c:\foo\file.txt} - 但事实上您只能使用 literal 路径并且您无法控制字符编码限制了它的用处。

然而,它允许有趣的用途;例如:

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

注:

  • 因为${<drive>:<path>}${<drive>:<path>} = <value>等同于
    Get-Content -Path <drive>:<path>Set-Content -Path <drive>:<path> <value>,路径被解释为通配符表达式(因为那是 -Path 所做的,而不是 -LiteralPath),这可能会导致 看起来像 通配符的路径问题 -有关示例和解决方法,请参阅

  • 在撰写本文时,命名空间变量符号尚未正式记录,但 this GitHub issue 建议这样做。