更新时间: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进行调用使转义cmd.exe
元字符的需求消失了,因为不涉及cmd.exe
.
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\`" }'"
bash
Bash与PowerShell一样,能够理解扩展(内插)的"..."
字符串和文字的'...'
字符串.
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\" }'"