电源外壳 7 : using ampersand (&) in string literals

标签 powershell

我正在尝试在 powershell 中执行以下命令,但不知道如何转义 & 字符,因为这是 url 的一部分

  az rest `
    --method GET `
    --uri ("https://graph.microsoft.com/v1.0/groups?`$count=true&`$filter=startsWith(displayName,'some+filter+text')&`$select=id,displayName") `
    --headers 'Content-Type=application/json'

因为 & 字符是用来开始一个新的命令,它打破了 url 并想执行其余的。

有没有办法告诉 powershell 不要这样做?

最佳答案

Olaf's answer提供有效的解决方案;让我添加一个解释:

问题的根源是两种行为的汇合:

  • 调用外部程序时,PowerShell按需根据给定参数值是否包含空格对每个参数执行双引号/em> - 否则,参数被传递 unquoted - 不管值是否在 PowerShell 命令中被 最初 引用(例如, cmd/c echo abcmd/c echo 'ab'cmd/c echo "ab" 都会导致 unquoted ab 作为命令行上的最后一个 token 传递,PowerShell 在幕后重建以最终用于执行)。

  • Azure az CLI 作为批处理文件 (az.cmd) 实现,当调用批处理文件时,解析给定参数的是 cmd.exe;令人惊讶 - 并且可以说是不恰当的 - 它解析它们就好像命令是从 cmd.exe session 中提交的一样。

因此,如果参数从 PowerShell 传递到批处理文件,该文件 (a) 不包含空格,但 (b) 包含 cmd.exe 元字符如&,调用breaks

一个简单的演示,使用 cmd/c echo 调用作为对批处理文件的调用的替代:

# !! Breaks, because PowerShell (justifiably) passes *unquoted* a&b
# !! when it rebuilds the command line to invoke behind the scenes.
PS> cmd /c echo 'a&b'
a
'b' is not recognized as an internal or external command,
operable program or batch file.

有三种解决方法:

  • 使用嵌入 "..." 引用:
# OK, but with a CAVEAT: 
#   Works as of PowerShell 7.2, but arguably *shouldn't*, because
#   PowerShell should automatically *escape* the embedded " chars. as ""
PS> cmd /c echo '"a&b"'
"a&b"

# Ditto, using an *expandable* (interpolating) PowerShell string:
PS> cmd /c echo "`"$HOME & Family; can't put a `$ value on that.`""
"C:\Users\jdoe & Family; can't put a $ value on that." # e.g. 
# OK, but with a CAVEAT:
#  Requires "..." quoting, but doesn't recognize *PowerShell* variables,
#  also doesn't support single-quoting and line continuation.
PS> cmd /c echo --% "a&b"
 "a&b"
  • 通过 cmd/c 调用并传递一个包含批处理文件调用及其所有参数的 single 字符串,(最终)使用 cmd。 exe的语法.
# OK (remember, cmd /c echo stands for a call to a batch file, such as az.cmd)
# Inside the single string passed to the outer cmd /c call,
# be sure to use "...", as that is the only quoting cmd.exe understands.
PS> cmd /c 'cmd /c echo "a&b"'
"a&b"

# Ditto, using an *expandable* (interpolating) PowerShell string:
PS> cmd /c "cmd /c echo `"$HOME & Family; can't put a `$ value on that.`""
"C:\Users\jdoe & Family; can't put a $ value on that." # e.g. 

后退一步:

现在,如果您不必担心所有这些事情会不会很好? 特别是因为您可能不知道或不关心给定的 CLI - 例如 az - 是否恰好发生 被实现为 作为批处理文件

作为一个 shell,PowerShell 应该尽最大努力在幕后忠实地传递参数,并允许调用者专门专注于仅满足 PowerShell 的语法规则:

  • 不幸的是,PowerShell 迄今为止(PowerShell 7.2)通常在这方面做得很差,不管 cmd.exe 的怪癖如何 - 请参阅this answer总结一下。

  • 关于 cmd.exe 的(批处理文件调用)怪癖,PowerShell 可以在未来的版本中可以预见地弥补它们 - 但看起来不幸的是,这种情况不会发生;见 GitHub issue #15143 .

关于电源外壳 7 : using ampersand (&) in string literals,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70841814/

相关文章:

powershell - 使用 New-Variable 函数创建变量时如何显式声明变量的类型?

windows - 如何使用 Ansible 将自定义脚本扩展添加到 Azure VM

powershell - 压缩存档错误 : PermissionDenied

powershell - 如何设置 PowerShell 脚本运行的时间限制?

powershell - PowerShell 中 Format-Table cmdlet 的最大列数是多少

powershell - 如何在 PowerShell 中使用反斜杠字符作为文字?

powershell - 通过 PowerShell 将所有已安装的软件分组到一个单元中

powershell - 验证参数真的有用吗?

PowerShell:上次执行结果是否有自动变量?

powershell - 命令完成后如何获取ReturnValue?