Olaf的回答提供了一个有效的解决方案;让我来解释一下:
问题的根源是两种行为的结合:
在调用外部程序时,PowerShell仅基于参数值是否包含空格执行按需双引号处理-否则,该参数将被传递不带引号-无论该值是否在PowerShell命令中原本被引用(例如,cmd /c echo ab
、cmd /c echo 'ab'
和cmd /c echo "ab"
都会导致未经引用的ab
作为最后一个标记传递给PowerShell在幕后重建并最终用于执行的命令行)。
Azure az
CLI是实现为批处理文件(az.cmd
),当调用批处理文件时,它是cmd.exe
解析给定的参数;令人惊讶的是-并且可以说是不适当的-它将它们解析为如果命令是从cmd.exe
会话内部提交的。
因此,如果从PowerShell 传递参数到批处理文件,并且该参数(a)不包含空格,但是(b)包含&
等cmd.exe
元字符,则调用将失败。
使用cmd /c echo
调用作为批处理文件的替代进行简单演示:
PS> cmd /c echo 'a&b'
a
'b' is not recognized as an internal or external command,
operable program or batch file.
有三种解决方法:
PS> cmd /c echo '"a&b"'
"a&b"
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.
PS> cmd /c echo --% "a&b"
"a&b"
- 通过
cmd /c
调用并传递一个包含批处理文件调用及其所有参数的 单个 字符串,最终使用 cmd.exe
的语法。
PS> cmd /c 'cmd /c echo "a&b"'
"a&b"
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的语法规则:
--%
。 - Olaf$filter=startsWith(displayName,'some+filter+text')" + '"&"' + "
$select=id,displayName")。但是这样会添加双引号,如果不加双引号,它又会失败。 - verbedr