Note: While this answer covers many aspects of string interpolation in PowerShell, a more comprehensive treatment of that topic can be found in this answer.
When embedding variable references in double-quoted strings, only simple variable references can be embedded without enclosing the expression in the so-called subexpression operator, $(...):
PS> $mylist = @("abc", "def") # define an array
PS> "$mylist[0]" # WRONG: $mylist (the whole array) is expanded, and "[0]" is a literal.
abc def[0]
PS> "$($mylist[0])" # OK: $(...) ensures that the subscript is recognized.
abc
To be more precise, you can directly embed the following variable references in double-quoted strings / here-strings in order to have them expanded (interpolated):
- a variable referenced by name only; e.g.,
"I'm $HOME."
- a variable with a scope specifier; e.g.,
"I'm on a spiritual $env:PATH."
To disambiguate a variable name from subsequent characters, enclose it in {...}; e.g.,
"I'm ${HOME}:"
Note that without {...}, the final : would have been interpreted as part of the variable name, and would have caused an error.
Alternatively, you could escape the : as `: and, similarly, use `$ to escape (create a literal) $.
For everything else, including accessing an array variable's subscript or an object variable's property, you need the subexpression operator, $(...).
Note that $(...) allows you to embed entire command lines in a string; e.g.:
PS> "Today is $((Get-Date).ToString('d'))."
Today is 10/13/16. # en-US culture
Documentation note: Get-Help about_Quoting_Rules covers string interpolation, but, as of PSv5, not in-depth.
For alternatives to string interpolation (expansion) for building strings, see Ansgar Wiecher's answer.