149

I always used the following syntax to be sure that variable were expanded in a string:

"my string with a $($variable)"

I recently ran into the following syntax:

"my string with a ${variable}"

Are they equivalent? Any difference?

3
  • 19
    $() is the sub-expression operator. It can enclose complex expressions or simple things like accessing member properties. ${} syntax is for when variable names have special symbols that otherwise standard $variable won't evaluate properly. Commented Feb 20, 2020 at 15:22
  • 3
    $() can also be used outside of strings to bring together multiple pipelines separated by a ";". Commented Feb 20, 2020 at 15:52
  • If anyone else here runs across issues with string interpolation, especially with nested hash table keys and values, I recommend setting the element you want to access as a temp variable with something like .ToString() or whatever data type would be appropriate. I wasted a lot of time trying to figure out why Write-Output was getting very different strings than the actual strings I was attempting to access, which showed up just fine when output to console directly. Commented Apr 5, 2023 at 22:25

3 Answers 3

193

tl;dr

Inside "...":

  • $(...) is only needed to embed entire expressions or commands (e.g. "$($PSVersionTable.PSVersion)")

  • ${...} is only needed if a stand-alone reference to a variable that has a regular name needs delimiting (disambiguation), so that subsequent characters in the string aren't interpreted as part of the variable name (e.g, "${foo}_bar" correctly embeds variable $foo; without {...}, PowerShell would look for variable $foo_bar; notably, a subequent : requires this technique too: "${foo}:bar")

Independently of use in "...", ${...} is also needed for variable names containing special characters (e.g. ${a-b} = 42)

For a comprehensive overview of PowerShell's expandable strings (string interpolation), see this answer.


Background information:

To complement marsze's helpful answer:

${...} (enclosing the variable name in { and }) is indeed always necessary if a variable name contains special characters, such as spaces, . or -.

Note:

  • ${...} - the syntax for disambiguating a variable name - is not to be confused with $(...), the subexpression operator, which is needed to embed any expression or command that goes beyond a stand-alone variable reference inside "...", an expandable (interpolating) string.

  • As such, these two syntax forms are independent of one another and may need to be combined in a given situation; e.g. "$var" / "${var}" work fine, but "$var.someProperty" / "${var}.someProperty" do not: you need "$($var.someProperty)" / "$(${var}.someProperty)"

In the context of "...", there is another reason to use ${...}, even if the variable name itself doesn't need it:

If you need to delineate the variable name from directly following non-whitespace characters, notably including ::

$foo = 'bar'  # example variable

# INCORRECT: PowerShell assumes that the variable name is 'foobarian', not 'foo'
PS> "A $foobarian."
A .  # Variable $foobarian doesn't exist -> reference expanded to empty string.

# CORRECT: Use {...} to delineate the variable name:
PS> "A ${foo}barian."
A barbarian.

# INCORRECT: PowerShell assumes that 'foo:' is a *namespace* (drive) reference
#            (such as 'env:' in $env:PATH) and FAILS:
PS> "$foo: bar"
Variable reference is not valid. ':' was not followed by a valid variable name character. 
Consider using ${} to delimit the name.

# CORRECT: Use {...} to delineate the variable name:
PS> "${foo}: bar"
bar: bar

See this answer for a comprehensive overview of PowerShell string-expansion rules.

Note that you need the same technique when string expansion is implicitly applied, in the context of passing an unquoted argument to a command; e.g.:

# INCORRECT: The argument is treated as if it were enclosed in "...",
#            so the same rules apply.
Write-Output $foo:/bar

# CORRECT
Write-Output ${foo}:/bar

Finally, a somewhat obscure alternative is to `-escape the first character after the variable name, but the problem is that this only works as expected with characters that aren't part of escape sequences (see about_Special_Characters):

# OK: because `: is not an escape sequence.
PS> "$foo`: bar"
bar: bar

# NOT OK, because `b is the escape sequence for a backspace character.
PS> "$foo`bar"
baar # The `b "ate" the trailing 'r' of the variable value
     # and only "ar" was the literal part.
Sign up to request clarification or add additional context in comments.

Comments

33

Note that $() is helpful for json objects:

"My json property is $($jsonObj.property)"

2 Comments

This is what I needed for ordinary PowerShell expressions, too.
To elaborate on @Grault's comment: { and } in ${var} are syntax elements in the context of referencing a variable alone, to disambiguate its name. By contrast, $(...) is the subexpression operator. As such, the two syntax forms are independent of one another and may need to be combined in a given situation. You need $(...) inside "..." for any expression that goes beyond a stand-alone variable reference; e.g. "$var" / "${var}" work fine, but "$var.someProperty" / "${var}.someProperty" do not: you need "$($var.someProperty)" / "$(${var}.someProperty)"
28

${variable} is the syntax for variable names that include special characters.

(See about_Variables -> Variable names that include special characters )

Example:

${var with spaces} = "value"
"var with spaces: ${var with spaces}"

So in your case it's basically the same as simply writing $variable

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.