我正在尝试在 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'
Run Code Online (Sandbox Code Playgroud)
由于 & 字符用于启动新命令,因此它会破坏 url 并希望执行其余部分。
有没有办法告诉 powershell 不要这样做?
mkl*_*nt0 10
奥拉夫的回答提供了一个有效的解决方案;让我添加一个解释:
问题的根源是两种行为的融合:
调用外部程序时,PowerShell仅根据给定参数值是否包含空格来按需对每个参数执行双引号- 否则,参数将不带引号传递- 无论该值最初是否在PowerShell命令中被引用(例如cmd /c echo ab,cmd /c echo 'ab'、 和cmd /c echo "ab"所有结果都会导致不带引号的 ab情况作为命令行上的最后一个标记传递(PowerShell 在幕后重建以最终用于执行)。
Azure CLI作为批处理文件( )az实现,当调用批处理文件时,它会解析给定的参数;令人惊讶的是——而且可以说是不恰当的——它解析它们,就好像命令是从会话内部提交的一样。az.cmdcmd.execmd.exe
因此,如果从 PowerShell 传递到批处理文件的参数(a) 不包含空格,但 (b) 包含cmd.exe元字符(例如&),则调用会中断。
一个简单的演示,使用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.
Run Code Online (Sandbox Code Playgroud)
有以下三种解决方法:
"..."引用:# 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.
Run Code Online (Sandbox Code Playgroud)
--%,停止解析标记- 但请参阅此答案的底部部分,了解 的限制--%及其相关的陷阱。# 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"
Run Code Online (Sandbox Code Playgroud)
cmd /c并传递包含批处理文件调用及其所有参数的单个字符串,(最终)使用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.
Run Code Online (Sandbox Code Playgroud)
退一步说:
现在,如果您不必担心所有这些事情,那不是很好吗?特别是因为您可能不知道或不关心给定的 CLI(例如)是否az恰好作为批处理文件实现?
作为 shell,PowerShell 应尽最大努力在幕后忠实地传递参数,并允许调用者专注于仅满足PowerShell 的语法规则:
不幸的是,迄今为止,PowerShell(PowerShell 7.2)在这方面通常做得很差,无论cmd.exe其怪癖如何 - 请参阅此答案以获取摘要。
对于cmd.exe(批处理文件调用)的怪癖,PowerShell可以预见地在未来版本中对其进行补偿 - 但不幸的是,这似乎不会发生;请参阅GitHub 问题 #15143。
| 归档时间: |
|
| 查看次数: |
3076 次 |
| 最近记录: |