Powershell:将json字符串传递给curl

发布于 2025-01-09 17:22:58 字数 1396 浏览 3 评论 0 原文

我正在尝试使用curl 将 JSON 字符串从 powershell 脚本内传递到 build.phonegap.com api。
根据 phonegap 论坛,在 Windows 计算机上运行时,必须格式化 JSON 数据如:

curl.exe -ku user@email:mypass -X PUT -d "data={\"password\":\"keypass\"}" https://build.phonegap.com/api/v1/key

Indeed, this does run fine when invoked from the command line.
However, when I try to invoke this from within a powershell script, the double quotes seem to be stripped.

到目前为止,我已经尝试过:

  • 将 JSON 放入单引号字符串中:
curl.exe -ku user@email:mypass -X PUT -d '"data={\"password\":\"keypass\"}"'  https://build.phonegap.com/api/v1/key
  • 将 JSON 放入单引号字符串中,无需 DOS 转义反斜杠:
curl.exe -ku user@email:mypass -X PUT -d '"data={"password":"keypass"}"'  https://build.phonegap.com/api/v1/key
  • 将 JSON 放在单引号字符串中,转义双引号和反斜杠(带反斜杠的 DOS 风格):
curl.exe -ku user@email:mypass -X PUT -d '\"data={\\\"password\\\":\\\"keypass\\\"}\"'  https://build.phonegap.com/api/v1/key
  • 将 JSON 放在双引号字符串中,使用 powershell 反引号字符转义双引号 (`):
curl.exe -ku user@email:mypass -X PUT -d "`"data={\`"password\`":\`"build*2014`\`"}`""  https://build.phonegap.com/api/v1/key

知道如何实现这一目标吗?

感谢您抽出时间, 科恩

I'm trying to pass a JSON string from within a powershell script to the build.phonegap.com api, using curl.
According to phonegap's forum, when running on a Windows machine, the JSON data has to be formatted as:

curl.exe -ku user@email:mypass -X PUT -d "data={\"password\":\"keypass\"}" https://build.phonegap.com/api/v1/key

Indeed, this does run fine when invoked from the command line.
However, when I try to invoke this from within a powershell script, the double quotes seem to be stripped.

So far, I have tried:

  • Putting the JSON in single quoted string:
curl.exe -ku user@email:mypass -X PUT -d '"data={\"password\":\"keypass\"}"'  https://build.phonegap.com/api/v1/key
  • Putting the JSON in single quoted string, without the DOS escape backslashes:
curl.exe -ku user@email:mypass -X PUT -d '"data={"password":"keypass"}"'  https://build.phonegap.com/api/v1/key
  • Putting the JSON in single quoted string, escaping the double quotes and backslashes (DOS style with a backslash):
curl.exe -ku user@email:mypass -X PUT -d '\"data={\\\"password\\\":\\\"keypass\\\"}\"'  https://build.phonegap.com/api/v1/key
  • Putting the JSON in a double quoted string, escaping the double quotes with the powershell backtick character (`):
curl.exe -ku user@email:mypass -X PUT -d "`"data={\`"password\`":\`"build*2014`\`"}`""  https://build.phonegap.com/api/v1/key

Any idea how to achieve this?

Thanks for your time,
Koen

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

金橙橙 2025-01-16 17:22:58

尝试使用 --% 运算符将 PowerShell 置于简单(哑)参数解析模式:

curl.exe --% -ku user@email:mypass -X PUT -d "data={\"password\":\"keypass\"}" https://build.phonegap.com/api/v1/key

这对于使用与 PowerShell 参数语法相冲突的参数语法调用 exe 通常很有用。这确实需要 PowerShell V3 或更高版本。

Try using the --% operator to put PowerShell into simple (dumb) argument parsing mode:

curl.exe --% -ku user@email:mypass -X PUT -d "data={\"password\":\"keypass\"}" https://build.phonegap.com/api/v1/key

This is quite often useful for invoking exes with argument syntax that runs afoul of PowerShell's argument syntax. This does require PowerShell V3 or higher.

执着的年纪 2025-01-16 17:22:58

更新

  • PowerShell 7.3.0 大部分修复了问题,Windows上有选择性例外 - 请参阅此答案以及下面的详细信息。

  • 对于跨版本、跨版本、跨平台代码,下面讨论的 Native 模块可能仍然令人感兴趣。

tl;dr

Windows PowerShellPowerShell (Core) 7 至 v7.2.x,不幸的是,您必须手动 \-转义参数传递给外部程序中嵌入的"字符

# From inside PowerShell:
# Note the outer '...' quoting and the unexpected need to escape
# the embedded " chars. as \" (unexpected, because PowerShell itself doesn't
# require " inside '...' to be escaped; also, PowerShell's escape char. is `).
# If outer "..." quoting must be used, use \`" (sic) to escape the embeded "
curl.exe -ku user@email:mypass -X PUT -d 'data={\"password\":\"keypass\"}' https://build.phonegap.com/api/v1/key

请继续阅读以了解原因

PowerShell 的转义


  • 字符是 `(所谓的反引号),因此为了嵌入 " 中的字符"..." (双引号,插值)字符串,使用 `" (或 "") 而不是 \";相比之下,在 '...'(单引号,逐字)字符串中," 需要不需要逃脱。

    • 在您的尝试中,PowerShell 并未将 \" 视为转义 ",因此看到多个< /em> "..." 字符串,最终 - 当 PowerShell 需要在幕后应用其按需重新引用时,传递了两个 > 由于不包含,单独的字符串参数不需要双引号空格,即:逐字 data={\password\:\keypass\}


    • 使用 PowerShell的引用规则,你应该用过

      • 要么:

        • "data={`"password`":`"keypass`"}"
      • 或者,更简单地说,假设不需要字符串插值,通过逐字引用的字符串,其中 "< /code> 字符不需要转义:

        • 'data={"password":"keypass"}'

      • 不幸的是,然而,直到 PowerShell 7.2.x,这还不够;请继续阅读以了解详细信息。




  • 直到 PowerShell 7.2.x,需要使用 \ 对嵌入的 " 字符进行意外的额外转义层 -调用(大多数)外部程序时转义

    • Windows PowerShell中,存在边缘情况此方法不起作用,在这种情况下使用--%是必需的(见下文)。值得注意的是,将 '"foo bar"' 转义为 '\"foo bar\"' 不起作用,因为包含 \"位于字符串的开头和结尾 - 有关详细信息,请参阅此答案

    • 此外,Windows 上的一些外部程序仅理解 ""-转义(例如 msiexec);对于它们,请使用 -replace '"', '""' 以编程方式执行额外的转义,假设该值至少包含一个空格。对不支持嵌入 < 的程序执行相同的操作代码>“字符。完全(WSH),这样嵌入的 " 至少不会打破参数边界(但它们将被剥离)。

    • 对于需要\"-转义的程序,请使用以下-replace操作来稳健执行额外的操作以编程方式转义:

      • '...' - 替换 '(\\*)"', '$1$1\"'
      • 如果输入字符串不包含预先存在的逐字 \" 序列,您可以简化为 '...' -replace '"', '\" ' 或者,为了获得更好的性能,'...'.Replace('"', '\"')



# Note: Escaping the embedded " chars. as `" is enough for PowerShell itself,
#       but, unfortunately, not when calling *external programs*.
#       The `-replace` operation performs the necessary additional \-escaping.
$passwd = 'foo'
curl.exe -ku user@email:mypass -X PUT -d (
  "data={`"password`": `"$passwd`"}" -replace '(\\*)"', '$1$1\"'
) https://build.phonegap.com/api/v1/key
  • 这不是必需的,但这是由于 v1 以来的错误由于担心破坏向后兼容性,该问题尚未修复 - 请参阅这个答案

  • PowerShell v7.3 大部分解决了该问题,但Windows 上有选择性例外

    • 选择性例外 - 请参阅$PSNativeCommandArgumentPassing 首选项变量 - 不幸的是,因为它们保留了例外列表中的程序的旧的、损坏的行为,特别是 cmd.exe 和 WSH(Windows 脚本主机)可执行文件及其关联的脚本文件 ( .cmd.bat.js.vbs.wsf),以及未来的风险,零碎地添加到例外列表中- 请参阅 GitHub 问题 #18660

      的摘要

    • 遗憾的是,通过 Windows 上备受瞩目的 CLI 的幕后调整来避免这些例外的机会被放弃了;请参阅 GitHub 问题 #15143 中的摘要。

  • 向后和向前兼容的辅助函数是来自Native module (Install-Module Native),它消除了额外转义的需要,包含高层人士的重要住宿即使修复到位, Windows 上的 CLI 将继续按预期工作:
    即curl.exe ... -d "data={`"password`": `"$passwd`"}" ... )

  • 使用-- %停止解析符号,如 Keith Hill 的答案 是一个次优解决方法,也不需要额外的 \-转义,但是

    • --% 具有固有的局限性 - 请参阅 GitHub 文档问题 #6149 - 在类 Unix 平台上几乎没有用 - 请参阅 GitHub 文档问题 #4963
    • --% 后面的参数中嵌入 PowerShell 变量值的唯一 - 尴尬且产生副作用 - 的方法是 (a) 将它们定义为 >环境变量(例如,$env:passwd = 'foo')和(b)引用这些变量cmd.exe-style< /em>,甚至在 Unix 上(例如, %passwd%)。


  • 替代解决方法 - 特别是如果您需要在调用中包含 PowerShell 变量或表达式的值 > - 是通过 cmd /c 调用,并使用包含整个命令行的单个参数;为了引用方便,以下示例使用此处字符串(请参阅此答案的底部部分 有关 PowerShell 字符串文字的概述):

# Use @"<newline>...<newline>"@ if you need to embed PowerShell variables / expressions.
cmd /c @'
curl.exe -ku user@email:mypass -X PUT -d "data={\"password\":"\keypass\"}" https://build.phonegap.com/api/v1/key
'@

Update:

  • PowerShell 7.3.0 mostly fixed the problem, with selective exceptions on Windows - see this answer and further below for details.

  • For cross-version, cross-edition, cross-platform code, the Native module discussed below may still be of interest.

tl;dr:

In Windows PowerShell and PowerShell (Core) 7 up to v7.2.x, you unfortunately must manually \-escape embedded " characters in arguments passed to external programs.

# From inside PowerShell:
# Note the outer '...' quoting and the unexpected need to escape
# the embedded " chars. as \" (unexpected, because PowerShell itself doesn't
# require " inside '...' to be escaped; also, PowerShell's escape char. is `).
# If outer "..." quoting must be used, use \`" (sic) to escape the embeded "
curl.exe -ku user@email:mypass -X PUT -d 'data={\"password\":\"keypass\"}' https://build.phonegap.com/api/v1/key

Read on for why that is necessary.


  • PowerShell's escape character is ` (the so-called backtick), so in order to embed " characters in a "..." (double-quoted, interpolating) string, use `" (or "") rather than \"; by contrast, inside a '...' (single-quoted, verbatim) string, " need not be escaped.

    • In your attempt, PowerShell didn't see \" as an escaped " and therefore saw multiple "..." strings, which ultimately - when PowerShell of necessity applied its on demand re-quoting behind the scenes, passed two separate string arguments that individually didn't need double-quoting, due to not containing spaces, namely: verbatim data={\ and password\:\keypass\}

    • Using PowerShell's quoting rules, you should have used:

      • either:

        • "data={`"password`":`"keypass`"}"
      • or, more simply, given that no string interpolation is needed, via a verbatim, single-quoted string, inside of which " chars. don't require escaping:

        • 'data={"password":"keypass"}'
      • Unfortunately, however, up to PowerShell 7.2.x this is NOT enough; read on for details.

  • Up to PowerShell 7.2.x, an unexpected extra layer of escaping of embedded " characters is needed, using \-escaping when calling (most) external programs:

    • In Windows PowerShell there are edge cases where this approach doesn't work, in which case use of --% is required (see below). Notably, escaping '"foo bar"' as '\"foo bar\"' doesn't work, due to the enclosing \" being at the very start and end of the string - see this answer for details.

    • Also, some external programs on Windows understand ""-escaping only (e.g. msiexec); for them, use -replace '"', '""' in order to programmatically perform the extra escaping, assuming the value contains at least one space. Do the same for programs that do not support embedded " chars. at all (WSH), so that the embedded " at least do not break argument boundaries (but they will be stripped).

    • For programs that expect \"-escaping, use the following -replace operation to robustly perform the extra escaping programmatically:

      • '...' -replace '(\\*)"', '$1$1\"'
      • If the input string contains no preexisting verbatim \" sequences, you can simplify to '...' -replace '"', '\"' or, for better performance, '...'.Replace('"', '\"')
# Note: Escaping the embedded " chars. as `" is enough for PowerShell itself,
#       but, unfortunately, not when calling *external programs*.
#       The `-replace` operation performs the necessary additional \-escaping.
$passwd = 'foo'
curl.exe -ku user@email:mypass -X PUT -d (
  "data={`"password`": `"$passwd`"}" -replace '(\\*)"', '$1$1\"'
) https://build.phonegap.com/api/v1/key
  • This shouldn't be required, but is due to a bug since v1 that hasn't been fixed for fear of breaking backward compatibility - see this answer.

  • PowerShell v7.3 mostly fixed the issue, but with selective exceptions on Windows.

    • The selective exceptions - see the description of the $PSNativeCommandArgumentPassing preference variable - are unfortunate, because they retain the old, broken behavior for the programs on the exception list, notably cmd.exe and the WSH (Windows Scripting Host) excecutables as well as their associated script files (.cmd, .bat, .js, .vbs, .wsf), with the risk of future, piecemeal additions to the exception list - see this summary from GitHub issue #18660

    • Sadly, an opportunity to avoid the need for these exceptions - via behind-the-scenes accommodations for high-profile CLIs on Windows - was passed up; see this summary from GitHub issue #15143.

  • A backward- and forward-compatible helper function is the ie function from the Native module (Install-Module Native), which obviates the need for the extra escaping, contains important accommodations for high-profile CLIs on Windows, and will continue to work as expected even with the fix in place:
    ie curl.exe ... -d "data={`"password`": `"$passwd`"}" ... )

  • Using --%, the stop-parsing symbol, as in Keith Hill's answer is a suboptimal workaround that also doesn't require the extra \-escaping, however:

    • --% has inherent limitations - see GitHub docs issue #6149 - and is virtually useless on Unix-like platforms - see GitHub docs issue #4963.
    • The only - awkward and side effect-producing - way to embed PowerShell variable values in the arguments following --% is to (a) define them as environment variables (e.g., $env:passwd = 'foo') and (b) to reference these variables cmd.exe-style, even on Unix (e.g., %passwd%).
  • An alternative workaround - especially if you need to include the values of PowerShell variables or expressions in your calls - is to call via cmd /c with a single argument containing the entire command line; for quoting convenience, the following example uses a here-string (see the bottom section of this answer for an overview of PowerShell's string literals):

# Use @"<newline>...<newline>"@ if you need to embed PowerShell variables / expressions.
cmd /c @'
curl.exe -ku user@email:mypass -X PUT -d "data={\"password\":"\keypass\"}" https://build.phonegap.com/api/v1/key
'@
北城挽邺 2025-01-16 17:22:58

终于找到了解决办法。我不使用一个 ",而是使用其中的 3 个 ("""),仅此而已。所以它会是:

data={"""password""":"""keypass"""}

Finally found the solution. Istead of using one " use 3 of them ("""), and thats it. So it would be:

data={"""password""":"""keypass"""}
往昔成烟 2025-01-16 17:22:58

以下是我如何在 PowerShell 7.2 中成功发送 json 请求
输入图片此处描述

Here's how I did manage to send a json request in PowerShell 7.2
enter image description here

毁虫ゝ 2025-01-16 17:22:58

我发现以下方法比转义字符更具可读性,并且在脚本中运行良好:

curl.exe -ku user@email:mypass -X PUT -d $(@{ password="keypass" } | convertto-json -compress) https://build.phonegap.com/api/v1/key

$( ) 在curl 本身之前执行,将哈希表对象转换为json。

关于 Convertto-json 的 Microsoft 文档:
https:// learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertto-json?view=powershell-7.4

I found the following way to be more readable than escaping the char and work fine inside scripts:

curl.exe -ku user@email:mypass -X PUT -d $(@{ password="keypass" } | convertto-json -compress) https://build.phonegap.com/api/v1/key

The $( ) is executed before the curl itself, converting the hashtable object to json.

Microsoft documentation on the convertto-json:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertto-json?view=powershell-7.4

纸短情长 2025-01-16 17:22:58

设置内容类型:

curl -H "Content-Type: application/json" -d '{"password":"keypass"}' https://build.phonegap.com/api/v1/key

Set the content type:

curl -H "Content-Type: application/json" -d '{"password":"keypass"}' https://build.phonegap.com/api/v1/key
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文