Search code examples
powershellstring-interpolationquoting

PowerShell formatting for a string


I have a string that I want to insert dynamically a variable. Example;

$tag = '{"number" = "5", "application" = "test","color" = "blue", "class" = "Java"}'

I want to accomplish:

$mynumber= 2
$tag = '{"number" = "$($mynumber)", "application" = "test","color" = "blue", "class" = "Java"}'

I want to have the variable inserted on the string, but it is not going through. I guess the '' sets all as a string. Any recommendations on how should I approach this?

PowerShell test and trial and error. Also Google.


Solution

  • To add to Mathias' helpful answer:

    • Mistakenly expecting string interpolation inside '...' strings (as opposed to inside "...") has come up many times before, and questions such as yours are often closed as a duplicate of this post.

    • However, your question is worth answering separately, because:

      • Your use case introduces a follow-up problem, namely that embedded " characters cannot be used as-is inside "...".

      • More generally, the linked post is in the context of argument-passing, where additional rules apply.


    Note: Some links below are to the relevant sections of the conceptual about_Quoting_Rules help topic.

    In PowerShell:

    • only "..." strings (double-quoted, called expandable strings) perform string interpolation, i.e. expansion of variable values (e.g. "... $var" and subexpressions (e.g., "... $($var.Prop)")

    • not '...' strings (single-quoted, called verbatim strings), whose values are used verbatim (literally).

    With "...", if the string value itself contains " chars.:

    • either escape them as `" or ""

      • E.g., with `"; note that while use of $(...), the subexpression operator never hurts (e.g. $($mynumber)), it isn't necessary with stand-alone variable references such as $mynumber:

        $mynumber= 2
        $tag = "{`"number`" = `"$mynumber`", `"application`" = `"test`",`"color`" = `"blue`", `"class`" = `"Java`"}"
        
      • Similarly, if you want to selectively suppress string interpolation, escape $ as `$

        # Note the ` before the first $mynumber.
        # -> '$mynumber = 2'
        $mynumber = 2; "`$mynumber` = $mynumber"
        
      • See the conceptual about_Special_Characters help topic for info on escaping and escape sequences.

      • If you need to embed ' inside '...', use '', or use a (single-quoted) here-string (see next).

    • or use a double-quoted here-string instead (@"<newline>...<newline>"@):

      • See Mathias' answer, but generally note the strict, multiline syntax of here-strings:
        • Nothing (except whitespace) must follow the opening delimiter on the same line (@" / @')
        • The closing delimiter ("@ / '@) must be at the very start of the line - not even whitespace may come before it.

    Related answers:


    Alternatives to string interpolation:

    Situationally, other approaches to constructing a string dynamically can be useful:

    • Use a (verbatim) template string with placeholders, with -f, the format operator:

      $mynumber= 2
      # {0} is the placeholder for the first RHS operand ({1} for the 2nd, ...)
      '"number" = "{0}", ...' -f $mynumber # -> "number" = "2", ...
      
    • Use simple string concatenation with the + operator:

      $mynumber= 2
      '"number" = "' + $mynumber + '", ...' # -> "number" = "2", ...