我正在尝试在 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 ab
、cmd/c echo 'ab'
和cmd/c echo "ab"
都会导致 unquotedab
作为命令行上的最后一个 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.
- 使用
--%
,stop-parsing token - 但请参阅 this answer 的底部部分--%
的局限性及其相关的陷阱。
# 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/