1

Using backslashes to pass a JSON string as a parameter in PowerShell is cumbersome.

executable --json-input '{ \"name\": \"Bob\" }' output.txt

Is there a way to avoid using these backslashes? I tried using single quotes, and doubles quotes in and out without any success. In Python I use triple quotes print(""" here is an example "" """) to avoid character escaping.

Is there a similar solution in PowerShell? One where we never need to worry about reformating a JSON string?

2
  • 1
    \" is not a valid escape sequence in PowerShell - are you perhaps referring to some other shell (bash/zsh/cmd)? Commented Jul 21, 2022 at 14:01
  • No, I'm really using PowerShell. It's strange because it really works on my side, here is the full command I use pastebin.com/P3pWBNya Commented Jul 21, 2022 at 14:17

2 Answers 2

3

PowerShell has here-strings, similar to the multiline literals from Perl (<<<) or Python (""").

The starting quote must be preceded by @ and immediately followed by a line break, whereas the closing quote must follow a newline and be followed by another @ sign:

command --json-input @"
{ "name": "Bob" }
"@ output.txt
Sign up to request clarification or add additional context in comments.

3 Comments

I edited my question, could you edit your answer too? I added a mandatory argument, how do you handle new lines in that case?
Your solution answers my question, but I realized that my issue isn't specific to PowerShell. It's specific to the AWS CLI.
While here-strings are a helpful pointer in general, note that use of regular single-quoted strings too doesn't require escaping " characters; e.g., '{ "name": "Bob" }. The need for \ escaping embedded " chars. only arises to work around PowerShell's broken argument-passing to external programs up to at least 7.2.x, and it applies whether or not you use here-strings.
2

The unfortunate need for manual \-escaping of " chars. embedded in string arguments passed to external programs is due to a long-standing PowerShell bug - see this answer - which is finally fixed in PowerShell 7.3+, with selective exceptions on Windows - see this answer.

  • That is to say, you should be able to just pass '{ "name": "Bob" }' - no \-escaping, but the bug prevents that.

To automate this escaping for now, without having to modify a given JSON string, you can apply a regex-based -replace operation, namely $json -replace '([\\]*)"', '$1$1\"'

# Note: only needed for *external executables*, up to at least PowerShell 7.2.x
executable --json-input ('{ "name": "Bob" }' -replace '([\\]*)"', '$1$1\"') output.txt

Note:

  • The above replacement operation also handles escaped embedded " characters correctly.

    • E.g., { "name": "Nat \"King\" Cole" } becomes
      { \"name\": \"Nat \\\"King\\\" Cole\" }, with the \ before " properly escaped as \\

    • See this regex101.com page for an explanation of the regex and replacement operation (for technical reasons, the linked page uses C#'s string syntax, but the solution is equivalent to what is shown here).

  • If you know your JSON input not to contain them, you can simplify to -replace '"', '\"'

4 Comments

Shouldn't it be -replace '(["\\])','\$1', not -replace '([\\]*)"', '$1$1\"'?
@Mathias, the replacement is designed to double (any non-empty run of) embedded \ chars. that directly precede a " in the input string. All other \ instances must be left alone.
@mklement0 is it here yet?
@shellwhale, yes, it was fixed in v7.3.0, but with selective exceptions on Windows - see stackoverflow.com/a/74440425/45375 for details.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.