6

Placing the following within a script will fail:

$MyString = @'
hello
@'
'@
bye
'@

write-host $MyString

The error returned is as follows:

At C:\scripts\test.ps1:6 char:1
+ '@
+ ~~
The string is missing the terminator: '.
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString

Prefixing the nested @' and '@ with a backtick (grave accent) does serve as an escape character, however it is also treated as literal, and therefore appears in the output of $MyString.

Is there a correct way to escape a single quoted here-string within a single quoted here-string that does not interfere with the output?

NB:

I should have mentioned that the content of the outer here-string is dynamically populated, the content is supplied by another program to the powershell script as a command line argument. This is not reflected in the sample code as I didn't want to cloud the question with my very specific and somewhat niche implementation.

It's not all that likely that the outer here-string will contain an inner here-string (but it could happen), therefore I feel that some defensive programming is warranted in order to accommodate such an occurrence.

3 Answers 3

4

Use double quotes, either for the outer here-string:

$MyString = @"
hello
@'
'@
bye
"@

or for the inner here-string:

$MyString = @'
hello
@"
"@
bye
'@
6
  • I use a single quoted here-sting in my script because it may contain HTML. If I use double quotes then javascript function calls would be misinterpreted as PowerShell sub-expressions and thus expanded.
    – Fitzroy
    Commented Oct 19, 2016 at 10:14
  • Then use double quotes for the inner here-string. Commented Oct 19, 2016 at 10:18
  • I have no control over the input supplied. An external process calls the powershell script, supplying the content of the here-string as an argument.
    – Fitzroy
    Commented Oct 19, 2016 at 10:40
  • 1
    Please update your question with a complete description of your problem. We're not playing 20 Questions here. Commented Oct 19, 2016 at 10:43
  • Please accept my apology - I do have control over the content within the outer here-string. Otherwise how would I escape it?? Changing the inner here-string to use double quotes I will accept it. That appears to be the cleanest way of updating the content with
    – Fitzroy
    Commented Oct 19, 2016 at 11:06
1

Try a ScriptBlock (enclosed in {}) instead of the outer Here-String. It works for the original example:

$MyString = {
hello
@'
'@
bye
}
write-host $MyString

Result:

PS > $MyString = {
>> hello
>> @'
>> '@
>> bye
>> }
>> write-host $MyString
>>

hello
@'
'@
bye

PS >

Note the extra blank lines at the beginning and the end. You can avoid them if you omit the line breaks after { and before }.

You may explicitly convert the ScriptBlock to a String with the ToString() function, if necessary.

Not sure if this workaround works in any use case, but it looks fairly clean, because the ScriptBlock takes all content without interpretation and is not confused by any curly braces nor is it interested in any quotes.

1

Regardless of whatever here-string quote character you choose, there is always the powershell escape character, the backtick

$MyString = @"
hello
@`'
`'@
bye
"@

is equivalent to

$MyString = @'
hello
@`'
`'@
bye
'@

If you need to esccape a backtick, just put 2 of them

Write-Host @"

here is a backtick ``

"@

Not the answer you're looking for? Browse other questions tagged or ask your own question.