我今天在 Powershell 5.1 中对变量名称使用制表符自动完成功能,并注意到其中一个选项是 PSDrive 的名称。驱动器名称是 docs
我想扩展名为 $document_name
.当我输入 $do<tab>
,shell 确实将我输入的内容扩展为 $document_name
但出于某种原因,我输入了 <tab>
第二次,那是扩展文本更改为 $docs:
的时候.
我进一步探索并发现我的每个 PSDrive 都存在这种类型的变量,或者至少选项卡扩展表明它存在。
更正式地说,对于每个 PSDrive PSD,选项卡扩展认为 $PSD:
是一个有效的东西。
我的问题很简单:这些到底是什么?以下是我到目前为止所做的一些观察:
- 这些名字的前缀是
$
, 所以它们看起来像 PS 变量。对于本次讨论的其余部分(以及上面之前的讨论),我将假设它们是变量并这样调用它们。 - 虽然它们看起来是变量,但它们并未列在
Variable:
中PSDrive 与大多数变量一样。这样,它的行为就像$env
“变量”,也未在Variable:
中列出.我有一种感觉,如果我能找到关于$env
的文档, 那么我也会理解这些对象。 - 在某些方面,它们的行为类似于指向文件系统对象的指针。例如,如果有一个文件名
readme.txt
包含文本“Hello, world!”在名为code
的 PSDrive 上, 那么以下所有都是与 Powershell 的可能交互。
获取文件的内容。
λ ${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-Member
,我收到一条错误消息 Variable reference is not valid
.
那么像 $env
这样的“变量”到底是什么?和 $<PSDrive>:
(例如 $code:
)?它们是表达式吗?内置表达式?某种物体?谢谢你的帮助。
最佳答案
您看到的是命名空间变量表示法,这是一种访问 PowerShell 驱动器中项目内容的基于变量的方法其底层提供程序实现基于内容的访问(即实现 IContentCmdletProvider
接口(interface))。
术语和文档说明:
- 在撰写本文时,文档简要在概念 about_Scopes 中解释了 namespace 变量表示法帮助主题,虽然没有使用该术语,并且在范围修饰符的上下文中讨论它,但有些令人困惑;虽然命名空间限定符(例如
$env:
)与范围修饰符(例如$script:
)无关,但是它们使用相同的基本语法 形式。 [1]
一般的语法是:
${<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:
)——尽管实际上没有意义,因为默认情况下省略驱动器部分会访问变量(例如,$variable:HOME
与$HOME
相同)。
其中,Env:
drive 是迄今为止最常与命名空间变量符号一起使用的,尽管大多数用户并不知道环境变量引用的基础是什么,例如 $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
),这可能会导致路径出现问题,看起来像 通配符 - 请参阅 this answer示例和解决方法。
[1] 以前,根本没有记录该功能; GitHub docs issue #3343导致了当前的文档,尽管不是按照上述问题提出的方式。
关于powershell - $<drivename> : (such as `$code:` ) in Powershell? 是什么类型的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55034497/