PowerShell Nested Here-String
Asked Answered
S

3

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.

Scincoid answered 19/10, 2016 at 9:47 Comment(0)
P
4

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

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

or for the inner here-string:

$MyString = @'
hello
@"
"@
bye
'@
Procto answered 19/10, 2016 at 10:10 Comment(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.Scincoid
Then use double quotes for the inner here-string.Procto
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.Scincoid
Please update your question with a complete description of your problem. We're not playing 20 Questions here.Procto
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 withScincoid
Argh - Don't have sufficent rep to edit comments. Apologies - I do have control over the content within the outer here-string. Otherwise how would I escape it?? Sorry. Changing the inner here-string to use double quotes appears to be the cleanest way of not adding additional characters to the output. I will accept your answer.Scincoid
C
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.

Chang answered 23/10, 2018 at 14:2 Comment(0)
S
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 ``

"@
Scifi answered 31/5, 2023 at 2:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.