What's the difference between
Write-Host (Get-Date) # just paren
and
Write-Host $(Get-Date) # dollar-paren
Content within the parens could be anything, just going with a simple example. Is there any difference between the two?
I consider myself reasonably experienced with PS, but it's these little things that bug me, especially during code review and the like. Has anyone come across a good source for "here is how the language works" with enough detail to derive answers to these sorts of questions?
The sub expression ($(...)
) contains a StatementBlockAst
. It can take any number of statements, meaning keywords (if
, foreach
, etc), pipelines, commands, etc. Parsing is similar to the inside of a named block like begin
/process
/end
.
The paren expression ((...)
) can contain a single ExpressionAst
which is a limited subset of the AST. The most notable difference between a statement and an expression is that keywords are not parsed.
$(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
Also as others have noted, the sub expression will expand in double quoted strings.
The ()
helps with order of operations
The $()
helps with evaluating values inside of the ()
For instance, if you're trying to find today's date in a string you could do the following:
echo "The length of Bryce is (Get-Date)"
echo "The length of Bryce is $(Get-Date)"
You'll see that the output is different (in one it gives you literally "(Get-Date)" whereas in the other it gives you the evaluated expression of Get-Date)
You can read more about syntax operators here
Parenthesis are used to group and establish order just as they do in mathematics. Starting in PowerShell v3 you can also use them to evaluate a property of a group, such as getting the file names for the files in the current folder by running:
(Get-ChildItem).Name
A sub-expression $()
evaluates the script within it, and then presents the output of that to be used in the command. Often times used within strings to expand a property of an object such as:
"Hello $($User.Name), would you like to play a game?"
It can also be useful when working with ComObjects, such as Excel where you may have a range that you want to test against a property of each item. While this does not work because the Range
object does not have a Font
property:
$Range.Font|Where{$_.Bold}
This would work, because it would output the Range
as a collection of Cell
objects, each of which have a Font
property:
$($Range).Font|Where{$_.Bold}
You can think of sub-expressions as being a script within your script, since they can be several commands long, and the entire thing is evaluated at once so that the end output can be used for the parent command.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With