()和$()的区别

6

什么是不同之处?

Write-Host (Get-Date) # just paren

并且

Write-Host $(Get-Date) # dollar-paren

括号内的内容可以是任何东西,这只是一个简单的例子。这两者之间有什么区别吗?

我认为自己在PS方面经验还不错,但正是这些小细节让我感到困扰,特别是在代码审查等方面。是否有人找到了一个好的资源,可以详细介绍语言的工作原理,足以得出这类问题的答案?


1
你可以尝试阅读《PowerShell语言规范3.0》的章节7.1.1“分组括号”和7.1.6“$()运算符——子表达式”。 - TessellatingHeckler
没错,就是这个。谢谢……把它作为答案,我会给它打上绿色的勾勾。 - Ken Hiatt
3个回答

12

子表达式 ($(...)) 包含一个 StatementBlockAst,它可以包含 任意数量 的语句,例如关键字(ifforeach 等)、管道、命令等。解析方式类似于命名块内部的解析,例如 begin/process/end

括号表达式 ((...)) 可以包含一个 单一的 ExpressionAst,它是 AST 的有限子集。语句和表达式之间最显著的区别是不解析关键字。

$(if ($true) { 'It worked!' })
# It worked!

(if ($true) { 'It worked!' })
# if : The term 'if' is not recognized as the name of a cmdlet, function, 
# script file, or operable program. Check the spelling of the name, or
# if a path was included, verify that the path is correct and try again.
# At line:1 char:2
# + (if ($true) { 'It worked' })
# +  ~~
#     + CategoryInfo          : ObjectNotFound: (if:String) [], CommandNotFoundException
#     + FullyQualifiedErrorId : CommandNotFoundException

正如其他人所指出的那样,子表达式将在双引号字符串中展开。


将此标记为“答案”;@TessellatingHeckler指向语言规范部分的指针实际上引导我深入挖掘我所追求的内容;这是一个很好的总结。 - Ken Hiatt

3

()函数有助于操作顺序。

$()函数有助于计算()内的值。

例如,如果您想在一个字符串中查找今天的日期,可以执行以下操作:

echo "The length of Bryce is (Get-Date)"
echo "The length of Bryce is $(Get-Date)"

你会发现输出结果不同(其中一个字面上给出了“(Get-Date)”而另一个则给出了Get-Date的计算表达式)。
你可以在这里阅读更多有关语法运算符的信息

1
我认为你提供的链接是沿着正确的方向,但引号内的用法与我的问题中引号外的用法不同。我还发现并正在仔细研究 v 3.0 语言规范(在此处:https://www.microsoft.com/en-us/download/details.aspx?id=36389),希望能给出明确的答案。 - Ken Hiatt
我已经更改了示例使用问题中使用的 cmdlet - 这是否更接近您要寻找的内容? - Bryce McDonald
不,当在引号内时,括号内部的处理方式是不同的。如果你做了像 $x = (Get-Date) 或 $x = $(Get-Date) 这样的事情,然后 'echo "stuff... $x" ',那么它会更符合我想要揭示的内容,即 PowerShell 是否会在括号前面加上 $ 处理任何不同的东西。 - Ken Hiatt

2

括号在计算数学时用于分组和建立顺序。从PowerShell v3开始,您还可以使用它们来评估组的属性,例如通过运行以下命令获取当前文件夹中文件的文件名:

(Get-ChildItem).Name

$()是一个子表达式,它会评估其中的脚本,并将其输出用于命令。通常在字符串中使用,以展开对象属性,例如:

"Hello $($User.Name), would you like to play a game?"

当使用ComObjects,例如Excel时,您可能需要测试每个项目的属性并针对范围进行操作,此时使用这种方法会很有用。尽管这种方法不起作用,因为Range对象没有Font属性:

$Range.Font|Where{$_.Bold}

这将起作用,因为它会将Range输出为Cell对象的集合,每个对象都有一个Font属性。
$($Range).Font|Where{$_.Bold}

您可以将子表达式视为脚本中的脚本,因为它们可以由多个命令组成,并且整个表达式会一次性地被计算,以便最终输出可用于父命令。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接