Windows PowerShell与Batch中=和.为何会拆分命令行参数?
现象成因解释
这个现象是批处理脚本的原生参数拆分规则和PowerShell的参数解析逻辑共同作用的结果,属于设计特性,不是Bug。
1. 批处理(.bat/.cmd)的参数拆分规则
CMD解释器执行批处理脚本时,默认会将=、,、;、空格等符号视为同等的参数分隔符,除非整个参数被双引号包裹:
- 单引号在CMD中没有参数包裹作用,会被当做参数内容的一部分
- 只有双引号包裹的内容才会被识别为单个完整参数
这就是在CMD中直接调用args.bat -a=b.c时,参数被拆为-a和b.c两个的原因。
2. PowerShell的参数解析规则
PowerShell有一套独立于CMD的参数绑定逻辑,调用外部程序(包括批处理脚本、原生exe)时,会先对输入的参数做一轮解析:
- 以
-开头的内容会被优先识别为参数标记 - 带
.的参数在PowerShell 5.1及更早版本中,会被额外拆分一次后缀内容 - PowerShell调用批处理脚本时,相当于先由PowerShell解析一轮参数,再传给CMD执行,CMD会再做一轮参数拆分,两层拆分就导致测试中
-a=b.c被拆成了三个参数。
3. 原生exe表现不同的原因
原生Windows可执行文件的参数传递逻辑和批处理完全不同:
- 调用exe时,系统会将整个命令行字符串完整传递给程序
- 参数拆分是由exe自身的运行时库完成的,微软Visual Studio编译的C程序默认使用的C运行时,仅会将空格、制表符等作为参数分隔符,不会把
=当做分隔符,因此CMD中直接调用exe可以拿到完整的-a=b.c参数 - PowerShell调用exe时,因为PowerShell自己先做了一轮参数拆分,才会出现
-a=b和.c被拆为两个参数的情况。
解决方案
- CMD环境:给带特殊符号的参数套双引号即可,例如
args.bat "-a=b.c"、doctest.exe "-tc=some.test.case" - PowerShell环境:
- 加
--%停止解析标记,PowerShell会原样传递后面的所有参数:.\doctest.exe --% -tc=some.test.case - 用转义双引号包裹参数:
.\doctest.exe"-tc=some.test.case"
- 加
内容的提问来源于stack exchange,提问作者zerox
相关产品推荐
相关产品推荐

