假设我的
AutoRun
脚本中有以下内容:
@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%%" ^
) ^
) ^
) ^
)
这应该是在
cd
中模仿 POSIX cmd.exe
的行为,并且在大多数情况下效果很好:
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
无论如何当命令扩展已启用,因为它不会将空格(或任何东西)视为分隔符一种简单的方法是对某些代码也使用定义批处理文件。
宏在最后使用
set args=
,然后调用主代码的批处理文件。@echo off
REM *** Trampoline jump for function calls of the form ex. "C:\:function:\..\MyBatchFile.bat"
FOR /F "tokens=3 delims=:" %%L in ("%~0") DO goto :%%L
doskey cd=for %%# in ( 1 1 2) do @if %%#==2 ( "%~d0\:__cd:\..\%~pnx0" ) else set args=$*
exit /b
:__cd
setlocal EnableDelayedExpansion
for /F "delims=" %%a in (""!args!"") DO (
endlocal
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%"
)
)
)
仅限Doskey:
但是如果你坚持只用 doskey 宏来解决它,你可以使用消失的插入符。
Line2 做的伎俩:
FOR %%^^^^ in ("") do
定义一个空的 %%^
FOR 元变量。
这用于
for /f "delims=" %%a in (^^""$*%%~^^"^")
%%~^^
转义下一个引号,但前提是 $*
包含不平衡的引号,并且在展开后 %%~^^
消失。$*
中不平衡引号的问题,因为在 $*
中没有或平衡引号的情况下,它扩展为
一个平衡的引号字符串,但这甚至适用于 $*
中的不平衡引号
doskey cd=( ^
FOR %%^^^^ in ("") do @for /f "delims=" %%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%%" ^
) ^
) ^
) ^
)