json - 如何将 JSON(字符串数据)传递给 PowerShell?
问题描述
我将以下内容作为参数传递给 powershell(w7 上的 v4):
-debugWrite -fileName SettingsFile -jsonContent { "c": "some setting", "d": "unknown", "b": "some thing", "a": 1 }
但是 PS 挂断了 JSON。我试过分隔 \double-quotes\ 并将 -jsonContent 之后的所有内容放在“单引号”中,但无济于事。
这是运行 PS 的 Windows 7 (PS4) 环境:
注意:“...”混淆是指相同的目录。IOW,所有文件都位于同一目录中。
运行一个批处理文件,开始整个过程:
"C:\...\script.bat" > "C:\...\script-output.txt" 2>&1
这运行script.bat
并输出到script-output.txt
. 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
传奇:
DropFileToCreate
- 传递给 PS 脚本的文件名,用于在同一目录中创建文件。
-jsonContent
- 脚本中的命名参数(请参阅下面的标题customscript.PS1
)
在上面的示例中,JSON 是:
"{ "c": "一些设置", "d": "未知", "b": "一些东西", "a": 1 }"
-debugWrite
- 一个开关参数(此处用于启用 Write-Host 调试)
最后,一点customscript.PS1
:
Param (
[Parameter(Mandatory = $True)]
[String]
$fileName,
[Parameter(Mandatory = $True)]
$jsonContent,
[Parameter(Mandatory = $False)]
[Switch]
$debugWrite = $False
)
[...]
JSON 更容易看到,并且解释了空格,如果表示为:
{
"c": "some setting",
"d": "unknown",
"b": "some thing",
"a": 1
}
解决方案
tl;博士
您的整体"..."
封闭 JSON 字符串已嵌入 "
,必须将其转义为\"
(原文如此;命令简化):
powershell.exe -File "C:\...\customscript.PS1" ... -jsonContent "{ \"c\": \"some setting\", \"d\": \"unknown\", \"b\": \"some thing\", \"a\": 1 }"
继续阅读以了解何时需要额外的转义、-File
调用与调用有何不同-Command
以及调用 shell(您从哪里调用powershell.exe
)的重要性。
笔记:
这个答案主要讨论了 Windows PowerShell可执行文件的使用
powershell.exe
,但它类似地适用于 PowerShell Core可执行文件,并且在底部pwsh
有一个关于调用的部分。bash
下面的从 PowerShell 本身调用部分,特别是 所需的语法
-File
,也适用于将 JSON 传递给其他程序,例如curl.exe
。
PowerShell CLI所需的语法(即powershell.exe
使用参数调用)取决于:
无论您是从
cmd.exe
(命令提示符/批处理文件)还是从 PowerShell 本身(或者,在 PowerShell Core中从类似 POSIX 的外壳程序,例如bash
)调用。是否将参数传递给
powershell -Command
(内联命令)或powerShell -File
(脚本路径)。
无论哪种方式,您最初的尝试都无法奏效,因为文字{ "c": "some setting" ... }
不能被识别为单个参数,因为包含空格并且没有被整体括在引号中;后来添加的命令,带有封闭"..."
,缺少嵌入的转义"
。
以下命令使用简化的 JSON 字符串演示了所讨论场景所需的语法。
要使命令可运行,请在当前目录中-File
创建一个文件。script.ps1
内容如下:ConvertFrom-Json $Args[0]
cmd.exe
从/批处理文件调用
Embedded
"
必须转义为\"
(即使您在内部`"
使用 PowerShell )。重要的:
- 如果 JSON 文本包含
cmd.exe
元字符(总是在\"...\"
运行之间),则必须^
单独对它们进行转义,因为cmd.exe
由于无法识别\"
为转义"
,因此认为这些子字符串未加引号;例如,\"some & setting\"
必须转义为\"some ^& setting\"
; 这里需要转义的cmd.exe
元字符是:
& | < > ^
- 如果 JSON 文本包含
cmd.exe
-style 环境变量引用,例如%USERNAME%
被插值-cmd.exe
没有文字字符串语法,它只识别"..."
,插值发生的地方,就像在不带引号的标记中一样。
如果您想按原样传递这样的标记,即抑制插值,则转义语法取决于您是从命令行调用还是从批处理文件调用,遗憾的是:%^USERNAME%
从前者使用,%%USERNAME%%
从后者使用 - 请参阅这个答案是血淋淋的细节。请注意,
-Command
调用如何通过将"..."
字符串包含在'...'
. 这是必需的,因为-Command
PowerShell 将其接收的参数视为 PowerShell源代码而不是文字参数(后者是 发生的情况-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\" }"
与-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
不涉及。PowerShell 的字符串引用规则适用,这简化了事情,但遗憾的是,您仍然需要手动
\
转义嵌入的"
字符。; 有关背景,请参阅此 GitHub 问题。更新:PowerShell Core 7.2.0-preview.5 引入了一个实验性的特性,
PSNativeCommandArgumentPassing
,它消除了手动\
转义的需要;尽管在这种情况下很有希望,但不能保证实验性功能成为常规功能;从 PowerShell Core 7.2.0-preview.5 开始,该功能是朝着正确方向迈出的一步,但在 Windows 上存在错误且缺乏 CLI 的重要调整 - 请参阅GitHub 问题 #15143。使用外部
'...'
引用简化了嵌入引用的语法,但这限制了您传递文字字符串。使用外部
"..."
允许您嵌入来自调用者的变量引用和表达式(在传递参数之前由调用者扩展),但它使语法复杂化,因为嵌入必须被双重转义为(原文如此):首先使用符合 PowerShell-内部语法,然后 with以满足 PowerShell CLI的要求。"
\`"
`
\
如果您的 JSON 文本不是文字并存储在变量中,则必须传递
$jsonVar -replace '"', '\"'
以执行必要的转义 - 请参阅此答案。
使用-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\`" }"
与-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核心:从bash
Bash 和 PowerShell 一样,既能理解扩展(内插)
"..."
字符串,也能理解文字'...'
字符串。Bash 与 不同
cmd.exe
,将其识别\"
为转义"
字符。inside"..."
,因此无需转义 Bash 的任何元字符。
与-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 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\" }'"
推荐阅读
- python-3.x - 使用 ArgumentParser 定义一个激活多个其他选项的选项;类似于 rsync -a
- apache-spark - 本地文件系统上的 Zeppelin 笔记本存储
- drools - 如何在 Drools 7.59 中测试列表长度?
- javascript - 输入字段上的Wordpress Javascript setAttribute
- php - PHP laravel 集合运行扁平化
- swift - 拖放验证
- machine-learning - 如何在 Hugging Face 预训练模型中使用自定义 Tokenizer 进行文本摘要?
- sql - SQL:如何连接两个表?
- python - CSV 到特定 JSON 结构
- mysql - 您的 SQL 语法有错误,请查看与您的 MySQL 服务器版本相对应的手册以获取正确的语法 '(TO_BASE64(RANDOM_BYTES(16)