我编写了一个批处理脚本,我想验证用户是否以正确的格式输入日期,例如
DD-MM-YYYY
。
但是我对变量有疑问。我可以使用命令
echo
显示其值,但是对变量值的进一步处理无法按预期进行,因此 if
条件也不起作用。我不明白问题出在哪里!
这是我的批处理脚本:
@echo off
cls
:A
echo.
set /p date=Quelle date souhaitez vous enregistrer (JJ-MM-AAAA) ?
for /f "tokens=1,2,3 delims=-" %%a in ("%date%") do (
set day=%%a
set month=%%b
set year=%%c
)
echo %day%
set date1 = %day%
echo %date1%
echo %month%
echo %year%
echo %date%
if "%date%" == %day%-%month%-%year%(echo yes) else (echo no)
goto :A
这是我的批处理文件执行时的输出:
Quelle date souhaitez vous enregistrer (JJ-MM-AAAA) ?09-09-09999
09
Commande ECHO désactivée.
09
0999
09-09-0999
Quelle date souhaitez vous enregistrer (JJ-MM-AAAA) ?
您可以看到
if
不起作用。我不明白为什么 %day%-%month%-%year%
为空。
请阅读 DosTips 论坛主题 ECHO。无法给出文本或空行 - 而是使用 ECHO/ 并在将来使用
echo(
,因为这是唯一可用的方法,始终输出空行而无需额外的文件系统访问。
请阅读我关于 如何阻止 Windows 命令解释器在用户输入不正确时退出批处理文件执行? 中的章节 使用 SET /P 获取用户提示
请打开命令提示符,运行
set /?
并阅读输出使用帮助。还简要解释了 dynamic 变量 DATE
,可以使用访问环境变量的语法来访问其当前值。
以下命令行导致用户真正输入字符串时定义环境变量
date
,从而在执行该命令行后无法访问动态变量DATE
的值,并且用户输入一个字符串。
set /p date=Quelle date souhaitez vous enregistrer (JJ-MM-AAAA) ?
请勿将 dynamic 变量的名称用于 environment 变量。
空格字符对于 Windows 命令处理器
cmd.exe
处理批处理文件来说是一个非常重要的字符。因此,批处理文件的作者必须注意在批处理文件的命令行中使用空格。
set date1 = %day%
使用环境变量 date1
的字符串值定义名称为 day
的环境变量是不正确的,正如我在 引用的答案还非常详细地描述了为什么建议使用语法
set "variable=value"
来防止定义环境变量时在字符串值上附加不需要的尾随空格,如 set month=%%b
内的命令行
for /f
所做的那样循环。
条件
if "%date%" == %day%-%month%-%year%
永远不会为真,因为在将左侧字符串与字符串比较运算符 ==
与比较运算符右侧的字符串进行比较时会考虑双引号。
请参阅我对 Windows 批处理文件中相当于 NEQ、LSS、GTR 等的符号的回答,了解有关如何通过命令 IF 分别
cmd.exe
完成字符串比较的完整详细信息。
由于缺少空格,以下命令行在语法上是错误的:
if "%date%" == %day%-%month%-%year%(echo yes) else (echo no)
不仅缺少
%day%-%month%-%year%
周围的双引号,而且还缺少 (echo
留下的空格字符,这会导致将 %day%-%month%-%year%(echo
解释为第二个字符串以与 "%date%"
和该行的其余部分进行比较作为执行命令。
但是这个命令行会导致执行:
if "09-09-0999" == 09-09 -0999(echo yes) else (echo no)
命令行上的尾随空格
set month=%%b
负责将字符串 "09-09-0999"
与字符串 09-09
进行比较,并将 -0999(echo yes) else (echo no)
解释为在正比较时执行的命令,如在 调试批处理文件中所示。条件永远不会成立,因此“命令”永远不会执行,否则会导致错误消息。
这里是一个带注释的批处理文件,只要不输入有效日期,就会提示用户输入日期。输入日期由批处理文件以安全可靠的方式进行验证。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
cls
echo(
goto DatePrompt
:InvalidDate
echo(
setlocal EnableDelayedExpansion
echo ERROR: !DateInput! is not a valid date string (%ErrorInfo%).
endlocal
echo(
:DatePrompt
set "DateInput="
set /P "DateInput=Quelle date souhaitez vous enregistrer (JJ-MM-AAAA)? " || goto DatePrompt
rem Remove all double quotes from the user input string.
set "UserDate=%DateInput:"=%"
rem Was there nothing else than one or more double quotes entered by the user?
if not defined UserDate set "ErrorInfo=no date string" & goto InvalidDate
rem The input date is invalid on third character not being a hyphen.
if not "%UserDate:~2,1%" == "-" set "ErrorInfo=invalid third character" & goto InvalidDate
rem The input date is invalid on fifth character not being a hyphen.
if not "%UserDate:~5,1%" == "-" set "ErrorInfo=invalid fifth character" & goto InvalidDate
rem The input date is invalid on having more than 10 characters.
if not "%UserDate:~10%" == "" set "ErrorInfo=too many characters" & goto InvalidDate
rem The input date is invalid on containing any other character than digits and hyphens.
for /F delims^=0123456789-^ eol^= %%I in ("%UserDate%") do set "ErrorInfo=invalid character" & goto InvalidDate
rem Split up the date into day, month and year.
for /F "tokens=1-3 delims=-" %%G in ("%UserDate%") do set "Day=%%G" & set "Month=%%H" & set "Year=%%I"
rem The input date is invalid on day having less than two digits.
if "%Day:~1%" == "" set "ErrorInfo=no two digit day" & goto InvalidDate
rem The input date is invalid on month having less than two digits.
if "%Month:~1%" == "" set "ErrorInfo=no two digit month" & goto InvalidDate
rem The input date is invalid on year having less than four digits.
if "%Year:~3%" == "" set "ErrorInfo=no four digit year" & goto InvalidDate
rem The year is valid now with a four digit value between 0000 and 9999.
rem Convert the day value from string to integer and back to string
rem with taking into account that a number with a leading zero would
rem be interpreted as an octal number which is avoided by prependig
rem the day string by the character 1 to change 00 to 99 to 100 to 199
rem and subtracting 100 to get as result a string in range 0 to 99.
set /A "DayValue=1%Day%-100"
rem The input date is invalid on day is zero.
if %DayValue% == 0 set "ErrorInfo=day is zero" & goto InvalidDate
rem Do the same as above for the month.
set /A "MonthValue=1%Month%-100"
rem The input date is invalid on month is zero.
if %MonthValue% == 0 set "ErrorInfo=month is zero" & goto InvalidDate
rem The input date is invalid on month greater than 12.
if %MonthValue% GTR 12 set "ErrorInfo=month greater 12" & goto InvalidDate
rem A standard year has 28 days in February.
set "February=28"
rem Is the month not February, verify day in month.
if not %MonthValue% == 2 goto VerifyDay
rem Find out now if the year is a leep year.
set /A "YearValue=1%Year%-10000"
rem Get the remainder of the division of the year by four.
set /A Result=YearValue %% 4
rem If the remainder is not zero, the year is not a leap year.
if not %Result% == 0 goto VerifyDay
rem Get the remainder of the division of the year by four hundred.
set /A Result=YearValue %% 400
rem If the remainder is zero, the year is a leap year.
if %Result% == 0 set "February=29" & goto VerifyDay
rem Get the remainder of the division of the year by one hundred.
set /A Result=YearValue %% 100
rem If the remainder is zero, the year is not a leap year.
if %Result% == 0 goto VerifyDay
rem The year is a leap year.
set "February=29"
:VerifyDay
for /F "tokens=%MonthValue%" %%I in ("31 %February% 31 30 31 30 31 31 30 31 30 31") do if %DayValue% GTR %%I set "ErrorInfo=day greater %%I" & goto InvalidDate
echo(
echo Congratulations: %UserDate% is a valid date.
echo(
pause
endlocal
要了解所使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。
cls /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
rem /?
set /?
setlocal /?
另请参阅 使用 Windows 批处理文件的单行多个命令,了解运算符
||
和 &
的说明。