4

This will surely be easy-goings for someone. When I reference an array item in a string, it is not producing the desired result. I expected the last statement to produce a string containing "abc", but it does not.

PS C:\src\powershell> $mylist = @("abc", "def")
PS C:\src\powershell> $mylist
abc
def
PS C:\src\powershell> $mylist[0]
abc
PS C:\src\powershell> $mylist[1]
def
PS C:\src\powershell> "$mylist[0]"
abc def[0]s
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
lit
  • 14,456
  • 10
  • 65
  • 119

2 Answers2

4

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.

mklement0
  • 382,024
  • 64
  • 607
  • 775
2

PowerShell doesn't recognize more complex variable constructs (e.g. index operations ($mylist[0]) or property/method access ($mylist.Count)) when expanding variables in strings. It will simply expand the variable and leave the rest of the string alone. Hence the expression "$mylist[0]" becomes "abc def[0]".

Basically you have three options to deal with this limitation:

Of course there are also more "exotic" approaches, like using the -join operator:

"-", $mylist[0], "-" -join ""

or replacement operations:

'-%x%-' -replace '%x%', $mylist[0]
'-%x%-'.Replace('%x%', $mylist[0])

but those already verge on obfuscation.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328