如何批量验证日期的格式?

问题描述 投票:0回答:1

我编写了一个批处理脚本,我想验证用户是否以正确的格式输入日期,例如

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%
为空。

batch-file
1个回答
0
投票

1.批处理文件代码错误

1.1 echo 的使用。输出空行

请阅读 DosTips 论坛主题 ECHO。无法给出文本或空行 - 而是使用 ECHO/ 并在将来使用

echo(
,因为这是唯一可用的方法,始终输出空行而无需额外的文件系统访问。

1.2 在进一步处理之前不验证用户输入字符串

请阅读我关于 如何阻止 Windows 命令解释器在用户输入不正确时退出批处理文件执行? 中的章节 使用 SET /P 获取用户提示

1.3 定义具有动态变量名称的环境变量

请打开命令提示符,运行

set /?
并阅读输出使用帮助。还简要解释了 dynamic 变量
DATE
,可以使用访问环境变量的语法来访问其当前值。

以下命令行导致用户真正输入字符串时定义环境变量

date
,从而在执行该命令行后无法访问动态变量
DATE
的值,并且用户输入一个字符串。

set /p date=Quelle date souhaitez vous enregistrer (JJ-MM-AAAA) ?

请勿将 dynamic 变量的名称用于 environment 变量。

另请参阅:CMD 中动态环境变量与普通环境变量的区别

1.4 环境变量定义中等号周围的空格

空格字符对于 Windows 命令处理器

cmd.exe
处理批处理文件来说是一个非常重要的字符。因此,批处理文件的作者必须注意在批处理文件的命令行中使用空格。

set date1 = %day%
使用环境变量
date1
的字符串值定义名称为
day
的环境变量是不正确的,正如我在
上的回答所详细解释的那样 为什么在命令行使用'set var = text'后没有'echo %var%'字符串输出?

引用的答案还非常详细地描述了为什么建议使用语法

set "variable=value"
来防止定义环境变量时在字符串值上附加不需要的尾随空格,如
set month=%%b  内的命令行 
for /f
 所做的那样
循环。

1.5 仅用双引号括起一个字符串的字符串比较

条件

if "%date%" == %day%-%month%-%year%
永远不会为真,因为在将左侧字符串与字符串比较运算符
==
与比较运算符右侧的字符串进行比较时会考虑双引号。

请参阅我对 Windows 批处理文件中相当于 NEQ、LSS、GTR 等的符号的回答,了解有关如何通过命令 IF 分别

cmd.exe
完成字符串比较的完整详细信息。

1.6 IF 条件中第二个字符串后缺少空格字符

由于缺少空格,以下命令行在语法上是错误的:

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)
解释为在正比较时执行的命令,如在 调试批处理文件中所示。条件永远不会成立,因此“命令”永远不会执行,否则会导致错误消息。

2.用于验证输入日期的批处理文件

这里是一个带注释的批处理文件,只要不输入有效日期,就会提示用户输入日期。输入日期由批处理文件以安全可靠的方式进行验证。

@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 批处理文件的单行多个命令,了解运算符

||
&
的说明。

© www.soinside.com 2019 - 2024. All rights reserved.