问题描述
我今天在 Powershell 5.1 中使用选项卡自动完成作为变量名,并注意到其中一个选项是 PSDrive 的名称.驱动器名称是 docs
,我想扩展的名称是 $document_name
.当我输入 $do<tab>
时,shell 确实将我输入的内容扩展为 $document_name
但出于某种原因,我输入了 <tab>
第二次,此时扩展文本变为 $docs:
.
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
and I wanted to expand is called $document_name
. When I typed $do<tab>
, the shell did indeed expand what I had typed to $document_name
but for some reason, I typed <tab>
a second time and that's when the expanded text changed to $docs:
.
我进一步探索发现,我的每个 PSDrives 都存在这种类型的变量,或者至少选项卡扩展表明它确实存在.
I explored further and found that this type of variable exists for each of my PSDrives, or at least tab expansion suggests that it does.
更正式地说,对于每个 PSDrive PSD,标签扩展认为 $PSD:
是一个有效的东西.
More formally, for every PSDrive PSD, tab expansion believes that $PSD:
is a valid thing.
我的问题很简单:这些到底是什么?以下是我迄今为止所做的一些观察:
My question is simple: what the heck are these? Here are some observations I've made so far:
- 这些名称以
$
为前缀,因此它们看起来像 PS 变量.对于本次讨论的其余部分(以及前面的讨论),我将假设它们是变量并照此引用它们. - 虽然它们看起来是变量,但它们并没有像大多数变量一样列在
Variable:
PSDrive 中.这样,它的行为就像$env
变量",它也没有在Variable:
中列出.我有一种感觉,如果我能找到关于$env
的文档,那么我也会理解这些对象. - 在某些方面,它们的行为类似于指向文件系统对象的指针.例如,如果文件名
readme.txt
包含文本Hello, world!"在名为code
的 PSDrive 上,则以下所有操作都是与 Powershell 的可能交互.
- These names are prefixed with
$
, so they look like PS variables. For the rest of this discussion (and in the earlier discussion above), I will assume they are variables and refer to them as such. - Although they appear to be variables, they are not listed in the
Variable:
PSDrive like most variables. In this way, it behaves like the$env
"variable," which also is not listed inVariable:
. I have a feeling if I could find documentation about$env
, then I'd understand these objects also. - In some ways, they behave like pointers to filesystem objects. For example, if there is a file name
readme.txt
containing the text "Hello, world!" on a PSDrive namedcode
, then all of the following are possible interactions with Powershell.
获取文件的内容.
λ ${code:
eadme.txt}
Hello, world!
只是为了证明上面结果的类型是String
:
Just to prove that the type of the above result is String
:
λ ${code:
eadme.txt} | % { $_.GetType().Name }
String
试图将其用作对 PSDrive 的引用对于许多操作都不起作用,例如 cd
:
Trying to use this as a reference to the PSDrive doesn't work well for many operations, such as 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
,我会收到错误提示 变量引用无效
.
I could go on, but I'm stumped. If I pass $code:
(or $env:
, for that matter) to Get-Member
, I get an error saying Variable reference is not valid
.
那么到底是什么变量",例如 $env
和 $<PSDrive>:
(例如 $code:
)?它们是表达式吗?内置表达式?某种对象?谢谢你的帮助.
So just what the heck are "variables" like $env
and $<PSDrive>:
(such as $code:
)? Are they expressions? Built-in expressions? Some kind of object? Thanks for any help.
推荐答案
你看到的是命名空间变量表示法,它是一个基于变量的在 PowerShell 驱动器中访问项目内容的方法,其底层提供程序实现基于内容的访问(即,实现 IContentCmdletProvider
接口).
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).
一般语法是:
${<drive>:<path>} # same as: Get-Content <drive>:<path>
${<drive>:<path>} = ... # same as: Set-Content <drive>:<path> -Value ...
如果 <drive>
名称和 <path>
都可以,则不需要包含 {...}
在语法上用作变量名;例如:
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 ")"
实际上,从 Windows PowerShell v5.1 开始,以下内置驱动器提供程序支持命名空间变量表示法:
In practice, as of Windows PowerShell v5.1, the following in-box drive providers support namespace variable notation:
- 环境(驱动
Env:
) - 函数(驱动
函数:
) - 别名(驱动
别名:
) - 文件系统(驱动
C:
, ...) - Variable (drive
Variable:
) - 虽然实际上没有意义,但在默认情况下省略驱动器部分会访问变量(例如,$variable:HOME
与刚才相同$HOME
).
- 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
).
其中,Env:
驱动器是迄今为止最常与命名空间变量表示法一起使用的驱动器,尽管大多数用户并不知道诸如 之类的环境变量引用的基础是什么$env: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
.
有时您会看到它与文件系统驱动器一起使用 - 例如,${c:foofile.txt}
- 但事实上您只能使用 literal 路径和你无法控制字符编码限制了它的用处.
On occasion you see it used with a filesystem drive - e.g., ${c:foofile.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
注意:
因为
${<drive>:<path>}
和${<drive>:<path>} = <value>
等价于Get-Content -Path <drive>:<path>
和Set-Content -Path <drive>:<path><value>
,路径被解释为 通配符表达式(因为这是-Path
所做的,而不是-LiteralPath
),这可能会导致看起来像通配符的路径出现问题 - 请参阅 this answer 示例和一种解决方法.
Because
${<drive>:<path>}
and${<drive>:<path>} = <value>
are equivalent toGet-Content -Path <drive>:<path>
andSet-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.
在撰写本文时,命名空间变量表示法尚未正式记录,但 this GitHub issue 建议这样做.
As of this writing, namespace variable notation isn't officially documented yet, but this GitHub issue suggests doing so.
这篇关于Powershell中的$<drivename>:(如`$code:`)是什么类型的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!