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

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

提问人:chris 提问时间:3/7/2019 最后编辑:chris 更新时间:11/17/2023 访问量:840

问:

我今天在 Powershell 5.1 中使用 Tab 自动完成作为变量名称,并注意到其中一个选项是 PSDrive 的名称。驱动器名称是,我想扩展的是 。当我键入时,shell 确实扩展了我键入的内容,但由于某种原因,我第二次键入,这时扩展的文本更改为 .docs$document_name$do<tab>$document_name<tab>$docs:

我进一步探索,发现我的每个 PSDrives 都存在这种类型的变量,或者至少 Tab 扩展表明它确实存在。

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

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

  • 这些名称以 为前缀,因此它们看起来像 PS 变量。对于本讨论的其余部分(以及上面前面的讨论),我将假设它们是变量,并这样称呼它们。$
  • 尽管它们看起来像变量,但它们不像大多数变量那样列在 PSDrive 中。这样,它的行为类似于“变量”,该变量也未在 中列出。我有一种感觉,如果我能找到关于 的文档,那么我也会理解这些对象。Variable:$envVariable:$env
  • 在某些方面,它们的行为类似于指向文件系统对象的指针。例如,如果 PSDrive 上有一个文件名包含文本“Hello, world!”,则 ,以下所有内容都可能与 Powershell 交互。readme.txtcode

获取文件的内容。

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

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

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

尝试将其用作对 PSDrive 的引用不适用于许多操作,例如: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-MemberVariable reference is not valid

那么,“变量”到底是什么样的,(例如)是什么?它们是表情吗?内置表达式?某种物体?感谢您的帮助。$env$<PSDrive>:$code:

PowerShell 命名空间 powershell-v5.1 new-psdrive

评论


答:

1赞 LeeM 3/7/2019 #1

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

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

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

正如 doco 中所说:

数据表示的模型是文件系统驱动器。使用数据 提供程序公开,您可以查看它,浏览它并更改它 就好像它是硬盘上的数据一样。因此,最重要的 有关提供程序的信息是它所在的驱动器的名称 支持。

6赞 mklement0 3/7/2019 #2

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

术语和文档说明

  • 在撰写本文时,文档简要解释了概念about_Scopes帮助主题中的命名空间变量表示法,尽管没有使用该术语,并且有些令人困惑的是,在范围修饰符的上下文中讨论了它;但是,虽然命名空间限定符(如 )与作用域修饰符(如 )无关,但它们使用相同的基本语法形式。[1]$env:$script:

一般语法为:

${<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:
  • 变量 (drive ) - 虽然实际上毫无意义,因为省略驱动器部分默认访问变量(例如,与 just 相同)。Variable:$variable:HOME$HOME

其中,驱动器是迄今为止最常使用命名空间变量表示法的驱动器,尽管大多数用户并不知道环境变量引用(如 .Env:$env:HOME

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

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

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

[1] 以前,根本没有记录该功能;GitHub 文档问题 #3343 导致了当前的文档,尽管不是以上述问题提出的方式。