如何在DOSKEY宏中清理命令参数以处理不完整引号?
问题:DOSKEY模拟POSIX cd宏处理不完整引号报错
我在AutoRun脚本中编写了如下DOSKEY宏,用于在cmd.exe中模拟POSIX cd命令的行为,多数场景下运行效果良好:
@doskey cd = @( ^ for /f usebackq^^ delims^^=^^ eol^^= %%a in (^ '$* ' ^ ) do @( ^ if "%%~a"==" " ( ^ if /i not "%%CD%%"=="%%USERPROFILE%%" ( ^ chdir /d "%%USERPROFILE%%" ^&^& ^ set "OLDPWD=%%CD%%" ^ ) ^ ) else if "%%~a"=="- " ( ^ if /i not "%%CD%%"=="%%OLDPWD%%" ( ^ chdir /d "%%OLDPWD%%" ^&^& ^ set "OLDPWD=%%CD%%" ^ ) ^ ) else ( ^ if /i not "%%CD%%"=="%%~a" ( ^ chdir /d "%%~a" ^&^& ^ set "OLDPWD=%%CD%%" ^ ) ^ ) ^ ) ^ )
运行示例如下:
C:\Users\user>cd C:\ C:\>cd C:\Users\user>cd - C:\>
但当输入不完整的双引号时,宏会报错:
C:\>cd " 2> was unexpected at this time.
我已尝试以下几种方法,但均未解决问题:
- 结合单引号使用
for /f(即示例中的写法):可处理参数列表的字符串比较,但仍无法应对不完整引号问题 - 将宏改为复合宏(如
for /l (1, 1, 2)...结合set args=,):无法在命令行上下文启用延迟扩展 - 用
$1、$2替代$*:DOSKEY不会按双引号分隔参数,且在启用命令扩展时不适用于chdir的内容
解决方案
问题根源是输入未闭合的双引号时,$*会将未闭合的引号带入for /f的单引号块中,导致cmd解析语法错误。可以通过启用延迟扩展先处理输入的引号完整性,再执行原逻辑,修改后的宏如下:
@doskey cd = @cmd /v:on /c "set ""input=$*"" & set ""quote_cnt=0"" & for /l %%n in (0,1,255) do (if ""!input:~%%n,1!""=="" goto quote_done & if ""!input:~%%n,1!""=="""" set /a quote_cnt+=1) & :quote_done & if !quote_cnt! equ 1 set ""input=!input!"""" & for /f delims^=^ eol^= %%a in (""!input!"") do (if ""%%~a""=="" "" (if /i not ""%%CD%%""==""%%USERPROFILE%%"" (chdir /d ""%%USERPROFILE%%"" && set ""OLDPWD=%%CD%%"")) else if ""%%~a""==""- "" (if /i not ""%%CD%%""==""%%OLDPWD%%"" (chdir /d ""%%OLDPWD%%"" && set ""OLDPWD=%%CD%%"")) else (if /i not ""%%CD%%""==""%%~a"" (chdir /d ""%%~a"" && set ""OLDPWD=%%CD%%"")))"
逻辑说明
- 使用
cmd /v:on启用延迟扩展,方便处理字符串操作 - 捕获输入到
input变量,统计其中双引号的数量 - 如果引号数量为奇数(即存在未闭合的引号),自动补全一个双引号
- 将处理后的输入传入
for /f执行原有的cd逻辑,避免语法错误
这样修改后,输入cd "时会自动补全引号为cd "",不会触发语法报错,同时不影响原有正常场景的使用。
内容的提问来源于stack exchange,提问作者mataha
相关产品推荐
相关产品推荐

