报价在DOS批处理文件通常被误用。与UNIX shell脚本不同,DOS批处理语言没有经过深思熟虑。例如,当isit
变量包含引号
set isit="Y"
那么上述if语句扩展到
IF ""Y"" == "Y" GOTO saidyes
IF ""Y"" == "N" GOTO saidno
因为cmd.exe的计算表达式之前不会删除"%isit%"=="Y"
引号。
isit
中的引用不应与在此处发布的原始批处理文件发生。但是,您经常在批处理文件中处理路径名,Windows将长文件名用引号引起来隐藏空白。例如,如“C:\ Program Files(x86)\ Microsoft Visual Studio 10.0 \ VC”。要解决这一点,通常的做法是写if语句这样:
IF ["%isit%"] == ["Y"] GOTO saidyes
IF [%isit%] == ["Y"] GOTO saidyes
IF [%isit%] == [Y] GOTO saidyes
对于set isit="Y"
变为:
IF [""Y""] == ["Y"] GOTO saidyes
IF ["Y"] == ["Y"] GOTO saidyes
IF ["Y"] == [Y] GOTO saidyes
和set isit=Y
:
IF ["Y"] == ["Y"] GOTO saidyes
IF [Y] == ["Y"] GOTO saidyes
IF [Y] == [Y] GOTO saidyes
和set isit=
:
IF [""] == ["Y"] GOTO saidyes
IF [] == ["Y"] GOTO saidyes
IF [] == [Y] GOTO saidyes
这远不够优雅,但至少现在适用于带引号和不带引号的变量。它也适用于isit
为空时。 Oftenly批处理文件停止,因为空的变量:
set x=
REM ...
IF %x% == x GOTO x
因为现在的if语句扩展为:
IF == x GOTO x
和CMD.EXE失败。这些错误通常很难调试。
诡计很古老;我记得在MSDOS中已经使用它。请注意,方括号不会被cmd.exe评估;他们只是一些很少使用的字符。但这只是一个窍门。任何先进的批处理脚本需要一个dequoting功能:
@echo off
setlocal EnableExtensions
setlocal EnableDelayedExpansion
REM ...
set /P isit="Y/N: "
call :dequote isit
REM ...
IF "!isit!" == "Y" GOTO saidyes
IF "!isit!" == "N" GOTO saidno
REM ...
goto done
:dequote
for /f "delims=" %%A in ('echo %%%1%%') do set %1=%%~A
goto :eof
:done
的deqote
-subroutine消除周围传递给函数的变量名称的任何双引号。
在引用[]
之后,就不再需要了。还请注意使用!
而不是%
。感叹号强制cmd.exe重新展开isit
。
啊...是的.. gotos ...嘿嘿。谢谢!我会在两分钟之内标记出来。谢谢! – nn2 2011-04-14 16:39:15
我复制粘贴上面的脚本,并得到与问题相同的问题。我删除了(),它工作。也许这不应该是被接受的答案。 – 2011-04-15 02:10:46
感谢Vik,在发布之前我还没有测试过我的代码(我目前在Linux上),结果如下...我刚更正了代码。 – cedrou 2011-04-15 08:21:18