json - 如何将 JSON(字符串数据)传递给 PowerShell?

标签 json powershell batch-file syntax quoting

我将以下内容作为参数传递给 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": "some setting", "d": "unknown", "b": "some thing", "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;博士
您的整体"..." -enclosed 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 的 shell,例如 bash)。
  • 是否将参数传递给 powershell -Command (内联命令)或 powerShell -File (脚本路径)。

  • 无论哪种方式,您最初的尝试都无法成功,因为文字 { "c": "some setting" ... }无法识别为单个参数 , 由于 包含空格 没有用引号括起来 总体;稍后添加的命令,包含 "..." , 缺少嵌入 " 的转义.
    以下命令使用简化的 JSON 字符串演示了所讨论场景所需的语法。
    使-File命令可运行,创建一个 script.ps1当前目录下的文件。内容如下:ConvertFrom-Json $Args[0]
    来自 cmd.exe 的来电/一个批处理文件
  • 嵌入式 "必须转义为 \" (即使在 PowerShell 内部您会使用 `" )。
  • 重要提示:
  • 如果 JSON 文本包含 cmd.exe元字符 (总是在 \"...\" 运行之间),您必须 ^ - 单独逃脱 , 因为 cmd.exe , 由于无法识别 \"作为逃跑者 " , 认为这些子串没有加引号;例如,\"some & setting\"必须转义为 \"some ^& setting\" ; cmd.exe这里需要转义的元字符是:& | < > ^

  • cmd.exe -style 环境变量引用 %USERNAME% 被插值 - cmd.exe没有文字字符串语法,它只识别 "..." ,插值确实发生的地方,就像在未引用的标记中一样。
    如果您想按原样传递这样的标记,即抑制插值,转义语法取决于您是从命令行还是批处理文件调用,遗憾的是:使用 %^USERNAME%来自前者,以及 %%USERNAME%%从后者 - 见 this answer对于血腥的细节。
  • 请注意 -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 的字符串引用规则适用,这简化了问题,尽管遗憾的是,您仍然需要手动\ -escape嵌入"字符。 ;见 this GitHub issue为背景。
  • 更新:PowerShell Core 7.2.0-preview.5 引入了 experimental feature , PSNativeCommandArgumentPassing ,无需使用本手册 \ - 逃跑;尽管在这种情况下很有希望,但不能保证实验性功能成为常规功能;从 PowerShell Core 7.2.0-preview.5 开始,该功能是朝着正确方向迈出的一步,但既有缺陷,又缺乏对 Windows 上 CLI 的重要调整 - 参见 GitHub issue #15143 .
  • 使用外 '...' quoting 简化了嵌入式引用的语法,但这限制了您只能传递文字字符串。
  • 使用外 "..."允许您嵌入来自调用者的变量引用和表达式(在传递参数之前由调用者扩展),但它使语法复杂化,因为嵌入的 "然后必须双重转义为 \`" (原文如此):首先是 `符合 PowerShell 内部语法,然后使用 \以满足 PowerShell CLI 的要求。
  • 如果您的 JSON 文本不是文字并存储在变量中,您必须传递 $jsonVar -replace '"', '\"'执行必要的转义 - 参见 this answer .


  • -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 , 识别 \"作为逃脱"字符。内"..." ,因此无需转义 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\" }'"
    

    关于json - 如何将 JSON(字符串数据)传递给 PowerShell?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53490414/

    相关文章:

    javascript - 如何在 JSON 对象中搜索特定字符串值?

    java - OkHttp 客户端不尊重 Accept header

    powershell - 在PowerShell中,有没有一种方法可以获取脚本参数的默认值?

    windows - 如果文件复制,则从 xcopy 获取通知

    javascript - GET 请求适用于 Postman,但为什么不适用于 ReactJS fetch?

    c# - Serilog 不产生预期的 json

    file - 需要创建批处理文件以从文件夹中选择一个随机文件并复制到另一个文件夹

    windows - 检测到文件夹中正在复制文件

    powershell - powershell 中 ForEach-Object 的语法

    powershell - Powershell调用Powershell脚本