【问题标题】:Validate the date given by user using batch file使用批处理文件验证用户给出的日期
【发布时间】:2016-11-30 20:37:36
【问题描述】:

使用批处理文件,我从用户那里获取日期。 现在,我想验证日期是否为 YYYY-MM-DD 格式。

我一直在搜索,但我在这里没有得到一些东西: 在某处找到了这个:

set /p startDate=Start Date [YYYY-MM-DD]: 
if "%startDate:~2,1%%startDate:~5,1%" neq "--" goto invalidDate
for /f "tokens=2 delims==" %%I in ("%startDate%") do set datetime=%%I
ver > NUL
set /A month=1%MM%-100, day=1%DD%-100, year=1%YYYY%-10000, leap=year%%4
if errorlevel 1 goto invalidDate
if not defined dpm[%month%] goto invalidDate
if %leap% equ 0 set dpm[2]=29
if %day% gtr !dpm[%month%]! goto invalidDate
if %day% lss 1 goto invalidDate
echo Date correct: %YYYY%-%MM%-%DD%

这些是什么: 〜2, 1%%变量:~5, %%, 在 cmd 帮助中,我找到了单 % 但不是双 %%

还有,

set /A month=1%MM%-100, day=1%DD%-100, year=1%YYYY%-10000, leap=year%%4

这实际上在做什么。谁能逐个解释一下?

【问题讨论】:

  • 我假设,因为代码现在错误,您更改了第一行以适应您的预期目标,但不知道它将如何影响其余部分。
  • 你是对的@Compo 我试图改变它并理解但它超出了我的头脑:P

标签: validation batch-file cmd


【解决方案1】:

有时会使用双 %(尽管我不知道确切的目的;我认为这是为了延迟扩展)但在您的情况下,它只是使用的两个变量的连接:

set foo=foo
set bar=bar
echo %foo%%bar%

->foobar

它的另一个用途(至少在批处理文件中)是在 for 循环中声明和使用变量:for /l %%I in(1,1,5) do echo %%i。在命令提示符下,您只会写 %i
说实话,您发布的第二行对我来说毫无意义... 感谢 Aacinis 的评论,现在这对我来说很有意义!基本上完成的是:

变量是 set/Arithmetic 项,其中 1 被添加到前面以再次减去它。示例:

set /a year=1%YYYY%-10000

-> 将变量 year 的值设置为变量 1YYYY - 10000 的值。这样做(感谢 Aacini 再次解释)以防止带有前导零(例如 08)的输入被解释为在这种情况下会导致无效日期的八进制值。请注意,是否使用/a 会有所不同:

set foo=1+1
set /a bar=1+1
echo foo %foo%
echo bar %bar%

接下来我们有另一个 %% 的情况,在这种情况下是模运算符。

如果您愿意,模运算符将返回除法的其余部分。例子:

10 %% 2 = 0(您可以将 10 除以 2 而无需任何余数)
11 %% 4 = 3(因为 8 乘 4 为 2,其余 8 到 11 为 3)

无论年份是闰年(值 == 0)还是不是(值!= 0),都会保存变量leap。然而,这在检查闰年时必须考虑的其他规则有点容易,但不属于这里......

%startDate:~2,1%%startDate:~5,1%

将生成一个字符串,该字符串在第一个 2 之后采用 1 字符,在第一个 5 之后采用 1 > 字符。在您的情况下,您必须将其更改为 ~4,1~7,1,因为第 5 和第 8 个字符是程序检查的破折号。

J.Baoby 建议this link 仔细看看。另外两个重要的帮助来源是 DostipsSS64

欢迎提问:)

【讨论】:

  • 我不认为%% 用于延迟扩展。在延迟扩展的情况下,您只需使用! 而不是%(如果您想使用delayed expansion%foo% 必须写为!foo!)。我知道 %% 用于访问变量的唯一地方是批处理脚本中的 for 循环。
  • 是的,这就是我写作的原因,我想……我以为我见过这样的东西,但我不确定。不过,for-loop 是一件好事,我将对其进行编辑。感谢您的建议!
  • 哦,好的。我的错。我的道歉,不客气。也许您还可以添加%var:~5,2% 用于从%var% 变量(从第6 个字符开始的2 个字符宽)中获取一个子字符串作为~5,1%This 可能是一个完美的链接
  • 不用道歉!我确实错了!另一件事要补充:)
  • 我喜欢这个解释! +1 :) 我只想补充一点,set /A month=1%MM%-100 技巧用于避免在%MM% 为 08 或 09 时出现错误,因为以“0”开头的数字被视为八进制数,但“08”和“09”是无效八进制数。我邀请您评论my answer
【解决方案2】:

您的程序肯定有一些代码问题,但我将为您提供一个替代方法来检查使用一点XCOPY 诡计的有效日期。它基本上使用 XCOPY 检查两个空文件夹以进行复制,但我们使用 /L 选项,这样它实际上不会复制任何内容。另一个技巧是,如果日期无效,它会在尝试复制之前抛出错误,我们可以使用它来重定向回问题以询问有效日期。

@echo off

:invalidDate
cls
set /p startDate=Start Date YYYY-MM-DD:

REM xcopy needs date in m-d-y format
for /f "tokens=1,2,3 delims=-" %%G in ("%startDate%") do set checkdate=%%H-%%I-%%G
set rand=%random%
md "dummy%rand%\empty%rand%"

xcopy /d:%checkdate% /t "dummy%rand%\empty%rand%" "dummy%rand%" >nul 2>&1 ||(
    rd /s /q "dummy%rand%" 
    goto invalidDate
    )

rd /s /q "dummy%rand%"
echo %startdate% is a valid date

pause

【讨论】:

  • 谢谢@Squashman 我只是想要一个解释,这样我就可以自己写或者至少理解发生了什么;)
【解决方案3】:

好吧,如果你拿一个工作代码,修改它然后你问“为什么这个代码不起作用?”,我认为答案是显而易见的......

这是你“在某处找到”的original code

@echo off
setlocal EnableDelayedExpansion

set i=0
for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do (
   set /A i+=1
   set dpm[!i!]=%%a
)

set /P "inDate=Please insert date (MM-DD-YYYY format): "
if "%inDate:~2,1%%inDate:~5,1%" neq "--" goto invalidDate
for /F "tokens=1-3 delims=-" %%a in ("%inDate%") do set "MM=%%a" & set "DD=%%b" & set "YYYY=%%c"
ver > NUL
set /A month=1%MM%-100, day=1%DD%-100, year=1%YYYY%-10000, leap=year%%4  2>NUL
if errorlevel 1 goto invalidDate
if not defined dpm[%month%] goto invalidDate
if %leap% equ 0 set dpm[2]=29
if %day% gtr !dpm[%month%]! goto invalidDate
if %day% lss 1 goto invalidDate
echo Date correct: %YYYY%-%MM%-%DD%
goto :EOF

:invalidDate
echo Bad date

如果要将原来的 MM-DD-YYYY 日期格式更改为 YYYY-MM-DD,则必须更改以下几行:

set /P "inDate=Please insert date (MM-DD-YYYY format): "
if "%inDate:~2,1%%inDate:~5,1%" neq "--" goto invalidDate
for /F "tokens=1-3 delims=-" %%a in ("%inDate%") do set "MM=%%a" & set "DD=%%b" & set "YYYY=%%c"

...由这些人:

set /P "startDate=Start Date [YYYY-MM-DD]: "
if "%startDate:~4,1%%startDate:~7,1%" neq "--" goto invalidDate
for /F "tokens=1-3 delims=-" %%a in ("%startDate%") do set "YYYY=%%a" & set "MM=%%b" & set "DD=%%c"

!dpm[%month%]! 部分的进一步解释见this answer。我邀请您阅读这样的答案并点赞它,因为它只需要几个点赞即可达到 100! ;)

【讨论】:

  • 该死的,我只需要再等一会儿......恭喜@Aacini :)
  • @Aacini 我知道我的代码不起作用。我确实更改了原始代码,但我无法理解它的任何内容。这就是为什么,我没有说我的代码不起作用:P 我只是想了解发生了什么,所以我就这样发布了它。对此感到抱歉;)非常感谢您的回答:)
  • 你最后的评论让我很困惑。我假设这个问题的目的是"Validate the date by user given using batch file",也就是说,为了修复发布的代码解决您的问题(验证用户输入)。恕我直言,如果您的 真正 目的不同,那么您应该将问题命名为“请解释这些批处理命令”,并仅发布您不理解的两三行。我建议您在以后的问题中尽可能简洁明了,不要包含任何与问题无关的额外代码/解释/数据...
  • 好的.. 我想你是对的.. 我刚刚发布了我正在研究的主题.. 当然,我下次会处理主题;)谢谢@Aacini
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-20
  • 1970-01-01
  • 2019-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多