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

2

0

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";
Dispensatory answered 10/4, 2019 at 12:15 Comment(1)
Use single quotes for the here string (not script block) to have the variables NOT expanded.Electroballistics
U
4

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
Unsaddle answered 10/4, 2019 at 13:51 Comment(0)
D
0

I couldn't find this anywhere, but it appears every single variable in the script (string literal) has to be escaped with a tick like so. Instead of deleting the question I'll leave it up for a search hit.

$multiLineScript2 = @"

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

"@
Dispensatory answered 10/4, 2019 at 12:24 Comment(3)
As @LotPings stated earlier, change your here string to use @' '@ instead of @" "@. Then you don't need to escape variables.Joeljoela
@Joeljoela It looks like OP want to expand some ($resultOfSubtraction), but not all variables.Bedspread
As PetSerAl states, it seems that selective suppression of expansion (interpolation) is the goal, which makes the phrase "every single variable in the script" confusing. The only good reason to use a double-quoted here-string (@"<newline>...<newline>"@) to begin with is if at least some expansion is needed.Unsaddle

© 2022 - 2024 — McMap. All rights reserved.