How can I write/create a powershell script verbatim, from another powershell script?

The following code (at the bottom) produces one of the following outputs in the file

4/12/2019 = (get-date).AddDays(2).ToShortDateString();
4/13/2019 = (get-date).AddDays(2 + 1).ToShortDateString();

or if I haven't initialized the variable

 = (get-date).AddDays(2).ToShortDateString();
 = (get-date).AddDays(2 + 1).ToShortDateString();

This is the code block, I would like the parent ps1 file to write the child ps1 file verbatim.

$multiLineScript2 = @"

    $startDate2 = (get-date).AddDays($resultOfSubtraction).ToShortDateString();
    $endDate2 = (get-date).AddDays($resultOfSubtraction + 1).ToShortDateString();
"@

$multiLineScript2 | Out-File "c:\file2.ps1";

Solution 1:

tl;dr:

To create a verbatim multi-line string (i.e., a string with literal contents), use a single-quoted here-string:

$multiLineScript2 = @'

    $startDate2 = (get-date).AddDays($resultOfSubtraction).ToShortDateString();
    $endDate2 = (get-date).AddDays($resultOfSubtraction + 1).ToShortDateString();
'@

Note the use of @' and '@ as the delimiters.

Use a double-quoted here-string only if string expansion (interpolation) is needed; to selectively suppress expansion, escape $ chars. to be included verbatim as `$, as shown in your own answer.


String Literals in PowerShell

Get-Help about_quoting rules discusses the types of string literals supported by PowerShell:

  • To get a string with literal content (no interpolation, what C# would call a verbatim string), use single quotes: '...'

    • To embed ' chars. inside a '...' string, double them (''); all other chars. can be used as-is.
  • To get an expandable string (string interpolation), i.e., a string in which variable references (e.g., $var or ${var}) and expressions (e.g., $($var.Name)) can be embedded that are replaced with their values, use double quotes: "..."

    • To selectively suppress expansion, backtick-escape $ chars.; e.g., to prevent $var from being interpolated (expanded to its value) inside a "..." string, use `$var; to embed a literal backtick, use ``
    • For an overview of the rules of string expansion, see this answer.

Both fundamental types are also available as here-strings - in the forms @'<newline>...<newline>'@ and @"<newline>...<newline>"@ respectively (<newline> stands for an actual newline (line break)) - which make defining multi-line strings easier.

  • Important:
    • Nothing (except whitespace) must follow the opening delimiter - @' or @" - on the same line - the string's content must be defined on the following lines.
    • The closing delimiter - '@ or "@ (matching the opening delimiter) - must be at the very start of a line.
    • Here-strings defined in files invariably use the newline format of their enclosing file (CRLF vs. LF), whereas interactively defined ones always use LF only.

Examples:

# Single-quoted: literal:
PS> 'I am $HOME'
I am $HOME

# Double-quoted: expandable
PS> "I am $HOME"
I am C:\Users\jdoe

# Here-strings:

# Literal
PS> @'
I am
  $HOME
'@
I am
  $HOME

# Expandable
PS> @"
I am
  $HOME
"@
I am
  C:\Users\jdoe