[英]How to pass JSON (string data) to PowerShell?
I'm passing the following as an argument to powershell (v4 on w7):我将以下内容作为参数传递给 powershell(w7 上的 v4):
-debugWrite -fileName SettingsFile -jsonContent { "c": "some setting", "d": "unknown", "b": "some thing", "a": 1 }
But PS gets hung up on the JSON.但是 PS 被 JSON 挂断了。 I've tried delimiting the \\double-quotes\\ and putting everything after -jsonContent in 'single quotes', but to no avail.
我试过分隔 \\double-quotes\\ 并将 -jsonContent 之后的所有内容放在“单引号”中,但无济于事。
Here is the Windows 7 (PS4) environment PS is running in:这是运行 PS 的 Windows 7 (PS4) 环境:
note: "..." obfuscation refers to the same dir.注意:“...”混淆指的是同一个目录。 IOW, all files live in the same directory.
IOW,所有文件都位于同一目录中。
A batch file is run, kicking off the whole thing:运行一个批处理文件,开始整个事情:
"C:\...\script.bat" > "C:\...\script-output.txt" 2>&1
This runs script.bat
and outputs to script-output.txt
.这将运行
script.bat
并输出到script-output.txt
。 script.bat
is a long 1-liner: script.bat
是一个很长的 1-liner:
%WINDIR%\sysnative\windowspowershell\v1.0\powershell.exe -ExecutionPolicy Bypass -File "C:\...\customscript.PS1" --% -fileName DropFileToCreate -jsonContent "{ "c": "some setting", "d": "unknown", "b": "some thing", "a": 1 }" -debugWrite
Legend:传奇:
DropFileToCreate
- the filename passed to the PS script, used to create a file in same dir. DropFileToCreate
- 传递给 PS 脚本的文件名,用于在同一目录中创建文件。
-jsonContent
- A named parameter in the script (see below for header of customscript.PS1
) -jsonContent
- 脚本中的命名参数(请参阅下面的customscript.PS1
标头)
In the above example, the JSON is:在上面的例子中,JSON 是:
"{ "c": "some setting", "d": "unknown", "b": "some thing", "a": 1 }"
"{ "c": "some setting", "d": "unknown", "b": "something", "a": 1 }"
-debugWrite
- A switch parameter (used here to enable Write-Host debugging) -debugWrite
- 开关参数(此处用于启用 Write-Host 调试)
Finally, a bit of the customscript.PS1
:最后,一些
customscript.PS1
:
Param (
[Parameter(Mandatory = $True)]
[String]
$fileName,
[Parameter(Mandatory = $True)]
$jsonContent,
[Parameter(Mandatory = $False)]
[Switch]
$debugWrite = $False
)
[...]
The JSON is easier seen, and spaces explained, if expressed as: JSON 更容易看到,空格解释,如果表达为:
{
"c": "some setting",
"d": "unknown",
"b": "some thing",
"a": 1
}
tl;dr tl;博士
Your overall "..."
-enclosed JSON string has embedded "
, which must be escaped as \\"
(sic; command simplified):您的整体
"..."
封闭的 JSON 字符串已嵌入"
,必须将其转义为\\"
(原文如此;命令已简化):
powershell.exe -File "C:\...\customscript.PS1" ... -jsonContent "{ \"c\": \"some setting\", \"d\": \"unknown\", \"b\": \"some thing\", \"a\": 1 }"
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.请继续阅读时需要额外的转义,如何
-File
的调用不同于-Command
调用,以及以何种方式调用shell(如你拨打powershell.exe
从)事宜。
Note:笔记:
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.此答案主要讨论了Windows PowerShell可执行文件
powershell.exe
,但它类似于 PowerShell Core可执行文件pwsh
,并且底部有一个关于从bash
调用的部分。
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下面,特别是与所需的语法调用部分
-File
,适用于通过JSON到其他程序如curl.exe
为好。
The required syntax for the PowerShell CLI - that is, invoking powershell.exe
with arguments - depends on : PowerShell CLI所需的语法- 即使用参数调用
powershell.exe
-取决于:
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
).无论您是从
cmd.exe
(命令提示符/批处理文件)还是从 PowerShell 本身(或者,在 PowerShell Core 中从类似 POSIX 的 shell 调用,例如bash
)。
whether you pass arguments to powershell -Command
(inline command) or是否将参数传递给
powershell -Command
(内联命令)或powerShell -File
(script path). powerShell -File
(脚本路径)。
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;无论哪种方式,您最初的尝试都无法奏效,因为文字
{ "c": "some setting" ... }
不能被识别为单个参数,因为包含空格而不是整体用引号括起来; the command added later, with enclosing "..."
, lacks escaping of the embedded "
.后来添加的命令,包含
"..."
,缺少对嵌入的"
转义。
The following commands demonstrate the required syntax for the scenarios discussed, using a simplified JSON string.以下命令使用简化的 JSON 字符串演示了所讨论场景所需的语法。
To make the -File
commands runnable, create a script.ps1
file in the current dir.要使
-File
命令可运行,请在当前目录中创建一个script.ps1
文件。 with the following content: ConvertFrom-Json $Args[0]
具有以下内容:
ConvertFrom-Json $Args[0]
cmd.exe
/ a batch filecmd.exe
/ 批处理文件调用Embedded "
must be escaped as \\"
(even though PowerShell- internally you'd use `"
).嵌入的
"
必须转义为\\"
(即使 PowerShell - 在内部你会使用`"
)。
Important:重要的:
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 ;cmd.exe
元字符(总是在\\"...\\"
运行之间),则必须单独^
-escape 它们,因为cmd.exe
由于未将\\"
识别为转义的"
,将这些子字符串视为未加引号; eg, \\"some & setting\\"
must be escaped as \\"some ^& setting\\"
;\\"some & setting\\"
必须转义为\\"some ^& setting\\"
; the cmd.exe
metacharacters that need escaping here are:cmd.exe
元字符是:& | < > ^
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. cmd.exe
风格的环境变量引用,例如%USERNAME%
是内插的- cmd.exe
没有文字字符串语法,它只识别"..."
,其中确实发生了内插,就像在未加引号的标记中一样。
If you want to pass such a token as-is, ie, 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.如果您想按原样传递这样的标记,即抑制插值,转义语法取决于您是从命令行调用还是从批处理文件调用,遗憾的是:使用前者的
%^USERNAME%
和%%USERNAME%%
来自后者的%%USERNAME%%
- 有关血腥细节,请参阅此答案。
Note how the -Command
calls simply add another layer of quoting, by enclosing the "..."
string in '...'
.请注意
-Command
调用如何通过将"..."
字符串包含在'...'
简单地添加另一层引用。 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
);这是必需的,因为使用
-Command
PowerShell 将其接收到的参数视为 PowerShell源代码而不是文字参数(后者是-File
发生的情况); if it weren't for the enclosing '...'
, the overall enclosing "..."
would be stripped before interpretation.如果不是封闭的
'...'
,整个封闭的"..."
将在解释之前被剥离。
With -File
:使用
-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\" }"
With -Command
:使用
-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\" }"'
Calling from PowerShell makes the need to escape cmd.exe
metacharacters go away, because cmd.exe
is not involved.从 PowerShell 调用使转义
cmd.exe
元字符的需要消失,因为cmd.exe
不涉及。
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. PowerShell 的字符串引用规则适用,这简化了问题,但遗憾的是,您仍然需要手动
\\
-escape 嵌入的"
字符。请参阅此 GitHub 问题以了解背景。
Update : PowerShell Core 7.2.0-preview.5 introduced an experimental feature , PSNativeCommandArgumentPassing
, which obviates the need for this manual \\
-escaping;更新:PowerShell Core 7.2.0-preview.5 引入了一项实验性功能
PSNativeCommandArgumentPassing
,无需使用本手册\\
-escaping; even though it is very much to be hoped for in this case, experimental features aren't guaranteed to become regular features;尽管在这种情况下很有希望,但不能保证实验性功能成为常规功能; as of PowerShell Core 7.2.0-preview.5, the feature is a step in the right direction, but is both buggy and lacks important accommodations for CLIs on Windows - see GitHub issue #15143 .
从 PowerShell Core 7.2.0-preview.5 开始,该功能是朝着正确方向迈出的一步,但既有缺陷,又缺乏对 Windows上CLI 的重要调整 - 请参阅GitHub 问题 #15143 。
Using outer '...'
quoting simplifies the syntax for the embedded quoting, but that limits you to passing literal strings.使用外部
'...'
引用简化了嵌入引用的语法,但这限制了您传递文字字符串。
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.使用外部
"..."
允许您嵌入来自调用者的变量引用和表达式(在传递参数之前由调用者扩展),但它使语法复杂化,因为必须将嵌入的"
双重转义为\\`"
(原文如此):首先使用`
以符合 PowerShell内部语法,然后使用\\
来满足 PowerShell CLI的要求。
If your JSON text is not a literal and stored in a variable , you must pass如果您的 JSON 文本不是文字并存储在变量中,则必须通过
$jsonVar -replace '"', '\\"'
to perform the necessary escaping - see this answer . $jsonVar -replace '"', '\\"'
执行必要的转义 - 请参阅此答案。
With -File
or when calling external programs such as curl.exe
:使用
-File
或调用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\`" }"
With -Command
:使用
-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
调用Bash, like PowerShell, understands both expanding (interpolating) "..."
strings and literal '...'
strings. Bash 与 PowerShell 一样,可以理解扩展(插入)
"..."
字符串和文字'...'
字符串。
Bash, unlike cmd.exe
, recognizes \\"
as escaped "
chars.与
cmd.exe
不同,Bash 将\\"
识别为转义的"
字符。 inside "..."
, so there's no need to escape any of Bash's metacharacters.在
"..."
,因此无需转义 Bash 的任何元字符。
With -File
:使用
-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\" }"
With -Command
:使用
-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\" }'"
I would suggest using a variable to pass the string.我建议使用变量来传递字符串。 For the example JSON given, it avoids escaping entirely.
对于给出的示例 JSON,它完全避免了转义。
ConvertFrom-Json
can be used as a test app. ConvertFrom-Json
可以用作测试应用程序。
First in PowerShell, observe首先在 PowerShell 中,观察
PS C:\> $psJson = '{ "c": "some setting", "d": "unknown", "b": "some thing", "a": 1 }'
PS C:\> ConvertFrom-Json $psJson
c d b a
- - - -
some setting unknown some thing 1
From CMD, we can achieve the same result.从 CMD 中,我们可以达到相同的结果。 When PowerShell is opened from a batch, it inherits the environment.
从批处理中打开 PowerShell 时,它会继承环境。 Instead of passing the string, set an environment variable and use it like a global
不是传递字符串,而是设置一个环境变量并将其用作全局变量
C:\>set dosJson={ "c": "some setting", "d": "unknown", "b": "some thing", "a": 1 }
C:\>powershell -command "& { ConvertFrom-Json $env:dosJson }"
c d b a
- - - -
some setting unknown some thing 1
EDIT:编辑:
It should be pointed out that this works for -Command
and not -File
, because the PowerShell environment is not available to the -File
args.应该指出的是,这适用于
-Command
而不是-File
,因为PowerShell的环境是不可用的-File
ARGS。 Of course you can run a script inside a -Command
.当然,您可以在
-Command
运行脚本。 Using a trivial test script test.ps1
使用一个简单的测试脚本
test.ps1
C:\>type test.ps1
param ([string] $json)
ConvertFrom-Json $json
C:\>powershell -command "& { C:\test.ps1 $env:dosJson }"
c d b a
- - - -
some setting unknown some thing 1
So the script.bat
in the question would have to be changed to -Command
.因此,问题中的
script.bat
必须更改为-Command
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.