且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何将JSON(字符串数据)传递到PowerShell?

更新时间:2023-11-03 18:16:46

tl; dr

您的整个"..."封闭的JSON字符串已嵌入 ",必须将其转义为\"(原文为sic;简化了命令):

Your overall "..."-enclosed JSON string has embedded ", which must be escaped as \" (sic; command simplified):

powershell.exe -File "C:\...\customscript.PS1" ... -jsonContent "{ \"c\": \"some setting\", \"d\": \"unknown\", \"b\": \"some thing\", \"a\": 1 }"

请继续阅读,了解何时需要进行其他转义,-File调用与-Command调用有何不同,以及调用外壳程序(在其中调用powershell.exe的位置)的重要性.

Read on for when additional escaping is needed, how -File invocation differs from -Command invocation, and in what way the calling shell (where you call powershell.exe from) matters.

注意:

  • 此答案主要讨论 Windows PowerShell 可执行文件powershell.exe的使用,但它类似地适用于PowerShell Core 可执行文件pwsh和底部有一个bash呼叫部分.

  • This answer primarily discusses use of the Windows PowerShell executable, powershell.exe, but it applies analogously to the PowerShell Core executable, pwsh, and there's a section on calling from bash at the bottom.

下面的从PowerShell自身调用部分,特别是-File所需的语法,也适用于将JSON传递给其他程序,例如curl.exe.

The section Calling from PowerShell itself below, specifically the syntax required with -File, applies to passing JSON to other programs such as curl.exe as well.

PowerShell CLI的必需语法-即,使用参数-依赖于 来调用powershell.exe:

The required syntax for the PowerShell CLI - that is, invoking powershell.exe with arguments - depends on:

  • 是从cmd.exe(命令提示符/批处理文件)调用,还是从PowerShell本身(或者在PowerShell Core 中,从类似POSIX的外壳(如bash)调用).

  • whether you're calling from cmd.exe (Command Prompt / batch file) or from PowerShell itself (or, in PowerShell Core from a POSIX-like shell such as bash).

是否将参数传递给powershell -Command(内联命令)或
powerShell -File(脚本路径).

whether you pass arguments to powershell -Command (inline command) or
powerShell -File (script path).

无论哪种方式,您最初的尝试都不会成功,因为文字 { "c": "some setting" ... }由于包含空格而不能被识别为单个参数 .总体而言,strong>和不在引号中;以后添加的带有"..."的命令缺少对嵌入式"的转义.

Either way, your original attempt could not have worked, because literal { "c": "some setting" ... } cannot be recognized as a single argument, due to containing whitespace and not being enclosed in quotes overall; the command added later, with enclosing "...", lacks escaping of the embedded ".

以下命令使用简化的JSON字符串演示了所讨论方案的必需语法.

The following commands demonstrate the required syntax for the scenarios discussed, using a simplified JSON string.

要使-File命令可运行,请在当前目录中创建一个script.ps1文件.包含以下内容:ConvertFrom-Json $Args[0]

To make the -File commands runnable, create a script.ps1 file in the current dir. with the following content: ConvertFrom-Json $Args[0]

  • 嵌入的"必须以\"的形式转义(即使内部使用PowerShell- ,也要使用`").

  • Embedded " must be escaped as \" (even though PowerShell-internally you'd use `").

重要提示:

  • 如果JSON文本包含cmd.exe 元字符 (总是在\"...\"次运行之间),则必须 ^-分别转义,因为cmd.exe由于未将\"识别为转义的",因此将这些子字符串视为不带引号的;例如,\"some & setting\"必须转义为\"some ^& setting\";需要在此处转义的cmd.exe元字符是:
    & | < > ^

  • If the JSON text contains cmd.exe metacharacters (invariably between \"...\" runs), you must ^-escape them individually, because cmd.exe, due to not recognizing \" as an escaped ", considers these substrings unquoted; e.g., \"some & setting\" must be escaped as \"some ^& setting\"; the cmd.exe metacharacters that need escaping here are:
    & | < > ^

cmd.exe样式的环境变量引用,例如%USERNAME% -cmd.exe没有 literal 字符串语法,它只能识别"...",在其中进行 插值,就像未加引号的标记中一样.
如果您想按原样传递这样的令牌,即传递给 suppress 插值,转义语法取决于您是从命令行还是批处理文件,可悲的是:使用前者的%^USERNAME%和后者的%%USERNAME%%-请参见此答案获取详细信息.

cmd.exe-style environment-variable references such as %USERNAME% are interpolated - cmd.exe has no literal string syntax, it only recognizes "...", where interpolation does take place, just as in unquoted tokens.
If you want to pass such a token as-is, i.e., to suppress interpolation, the escaping syntax depends on whether you're calling from the command line or a batch file, sadly: use %^USERNAME% from the former, and %%USERNAME%% from the latter - see this answer for the gory details.

请注意,通过将"..."字符串括在'...'中,-Command调用是如何简单地添加另一层引用.这是必需的,因为对于-Command,PowerShell将接收到的参数视为PowerShell 源代码,而不是作为文字参数(后者与-File一起发生).如果不是用于封闭的'...',则在解释之前将整个封闭的"..."剥掉 .

Note how the -Command calls simply add another layer of quoting, by enclosing the "..." string in '...'. This is required, because with -Command PowerShell treats the arguments it receives as PowerShell source code rather than as literal arguments (the latter is what happens with -File); if it weren't for the enclosing '...', the overall enclosing "..." would be stripped before interpretation.

使用-File :

With -File:

# With a literal string:
powershell -File ./script.ps1 "{ \"c\": \"some setting\", \"unknown\": \"b\" }"

# With an expandable string (expanded by the caller):
powershell -File ./script.ps1 "{ \"c\": \"some %USERNAME%\", \"unknown\": \"b\" }"

使用-Command :

With -Command:

# With a literal string:
powershell -Command ConvertFrom-Json '"{ \"c\": \"some setting\", \"unknown\": \"b\" }"'

# With an expandable string (expanded by the caller):
powershell -Command ConvertFrom-Json '"{ \"c\": \"some %USERNAME%\", \"unknown\": \"b\" }"'


从PowerShell本身调用

  • 从PowerShell进行调用使转义cmd.exe元字符的需求消失了,因为不涉及cmd.exe.


    Calling from PowerShell itself

    • Calling from PowerShell makes the need to escape cmd.exe metacharacters go away, because cmd.exe is not involved.

      使用PowerShell的字符串引用规则,这简化了事情,尽管可悲的是,您仍然需要手动\ -escape嵌入式"字符..有关背景信息,请参见此GitHub问题.

      PowerShell's string-quoting rules apply, which simplifies matters, although, sadly, you still need to manually \-escape embedded " chars.; see this GitHub issue for background.

      • 使用外部'...'引号可简化嵌入式引号的语法,但是将您限制为传递 literal 字符串.

      • Using outer '...' quoting simplifies the syntax for the embedded quoting, but that limits you to passing literal strings.

      使用外部"..."允许您嵌入来自调用方的变量引用和表达式(由 caller 扩展,之前传递) ,但是它使语法变得复杂,因为随后必须以\`"(原文如此)对嵌入式"进行双重转义:首先使用`符合PowerShell- internal 语法,然后使用\满足PowerShell CLI 的要求.

      Using outer "..." allows you to embed variable references and expressions from the caller (which are expanded by the caller, before the argument is passed), but it complicates the syntax, given that an embedded " must then be doubly escaped as \`" (sic): first with ` to conform to PowerShell-internal syntax, then with \ to satisfy the PowerShell CLI's requirements.

      如果您的JSON文本不是文字且存储在变量中,则必须传递
      $jsonVar -replace '"', '\"'来执行必要的转义-请参见

      If your JSON text is not a literal and stored in a variable, you must pass
      $jsonVar -replace '"', '\"' to perform the necessary escaping - see this answer.

      使用-File或调用外部程序(例如curl.exe )时:

      With -File or when calling external programs such as curl.exe:

      # With a literal string:
      powershell -File ./script.ps1 '{ \"c\": \"some setting\", \"unknown\": \"b\" }'
      
      # With an expandable string (expanded by the caller):
      powershell -File ./script.ps1 "{ \`"c\`": \`"some $env:OS\`", \`"unknown\`": \`"b\`" }"
      

      使用-Command :

      With -Command:

      # With a literal string:
      powershell -Command ConvertFrom-Json '''"{ \"c\": \"some setting\", \"unknown\": \"b\" }"'''
      
      # With an expandable string (expanded by the caller):
      powershell -Command ConvertFrom-Json "'{ \`"c\`": \`"some $env:OS\`", \`"unknown\`": \`"b\`" }'"
      


      PowerShell Core :从bash

      调用
      • Bash与PowerShell一样,能够理解扩展(内插)的"..."字符串和文字的'...'字符串.


        PowerShell Core: Calling from bash

        • Bash, like PowerShell, understands both expanding (interpolating) "..." strings and literal '...' strings.

          Bash与cmd.exe不同,将\"识别为转义的"字符.在"..."中,因此无需转义Bash的任何元字符.

          Bash, unlike cmd.exe, recognizes \" as escaped " chars. inside "...", so there's no need to escape any of Bash's metacharacters.

          使用-File :

          With -File:

          # With a literal string:
          pwsh -File ./script.ps1 '{ "c": "some setting", "unknown": "b" }'
          
          # With an expandable string (expanded by the caller):
          pwsh -File ./script.ps1 "{ \"c\": \"some $USER\", \"unknown\": \"b\" }"
          

          使用-Command :

          With -Command:

          # With a literal string:
          pwsh -Command ConvertFrom-Json \''{ "c": "some setting", "unknown": "b" }'\'
          
          # With an expandable string (expanded by the caller):
          pwsh -Command ConvertFrom-Json "'{ \"c\": \"some $USER\", \"unknown\": \"b\" }'"