PowerShell字符串格式:为什么冒号字符导致我的变量值为空?

时间:2011-12-05 13:42:48

标签: powershell

我正在研究下一个WinRM和PowerShell 3会发生什么,我正在查看重大变化列表,看到了一些我以前从未见过的东西。

例子是:

$server = "msp42"
$status = "online"
"$server: $status"

结果输出为:

  

在线

好吧,我以前从未遇到过这种情况,也不知道为什么结肠会引起问题。 文档中建议的解决方案是放置一个空格(因为你改变了输出,这是愚蠢的):

"$server : $status"

另一个建议是使用这种格式(对我来说是新的!):

"${server}: $status"

最后的建议是制作一个我熟悉并且一直使用的表达式:

"$($server): $status"

所以,我向你提出的PowerShell大师的问题是:

  1. 结肠怎么了?是某事?

  2. ${variable}语法到底是什么?是严格处理结肠还是有一些整洁的功能?

2 个答案:

答案 0 :(得分:39)

冒号是变量名称的有效字符,例如在$Env:PATH等等

您也可以使用以下选项

$server`: $status

或者,在某些情况下,格式字符串更具可读性:

'{0}: {1}' -f $server, $status

回到结肠。对于与PSDrive上的项目对应的变量名称有一个特例:

$Env:Foo           # equivalent to the contents of Env:\Foo
$Function:C:       # equivalent to the contents of Function:\C:
${C:\autoexec.bat} # ... you get the picture

语法${}的存在是为了能够指定变量名称,否则这些变量名称将使用为语法的其他部分保留的字符。您可以在标识符前面看到它与C#的@相似(但更强大)。请参阅上面变量名称中使用\的情况,因为$Drive:Item仅适用于驱动器上的当前容器(或Env之类的非分层容器的根目录,{{1 }或Alias)。

另一个例子,变量名通常是无效的语法:

Function

答案 1 :(得分:8)

这是前几天在Windows PowerShell脚本中绊倒我的东西。假设您必须使用变量$ user和$ machine,并且希望打印一个字符串,其值均以冒号(':')分隔。

显然你可以使用字符串连接来实现:

$user = 'tomasr' 
$machine = 'arcano' 

write ($user + ':' + $machine)

这样可行,但PowerShell不支持那种漂亮的字符串插值功能吗?为什么,是的呢!那么我们为什么不这样重写呢:

write "$user:$machine"

但是等等!如果你运行最后一行,你得到的只是$ machine变量的值... $ user go在哪里?

答案是冒号在PowerShell变量名中有特殊含义:它用于将变量与特定范围或命名空间相关联。 PowerShell定义了一些范围,例如script和global;例如,全局变量可能被命名为$ global:var。

但是我们还没有在其他地方看到过这种语法吗?当然,$ env:PATH怎么样?一样;除了这里env本身不是一个范围,而是一个PSDrive。因此':'之前的部分可以是PS定义的实际范围,也可以是PSDrive。哎呀,你甚至可以尝试“$ {c:autoexec.bat}”之类的东西,看看神奇的事情发生了!

因此我们的字符串插值的问题是,当PowerShell看到"$user:$machine"时,它希望找到名为'user'的范围/ psdrive,并期望变量名称跟随':',但'$'isn无效,'用户'也不是范围或PSDrive,这会让PowerShell感到困惑。但是因为他太绅士了,所以他尽可能地把它修好,并且忽略了到目前为止所做的一切,只是抛弃了机器而没有抱怨。对他很好,但是如果你没想到的话,它真的会让你失望!

我们能避免这种情况吗?是的,我们可以通过使用“{}”简单地为PowerShell分隔变量名称,如下所示:

write "${user}:$machine"

Bruce Payette卓越的Windows PowerShell in Action第141页第5.8节介绍了PowerShell中变量的主题,并为我提供了解决此问题的线索。