[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
应该是用到了多个模式串来处理不同月份不同天数的问题
只是平闰年判断尚没有不用set的思路

一般的检测日期的方法除了简单判断溢出之外
就是使用日期的命令来辅助检测了
date是最常用的比如10楼的方案
不过它有个缺陷就是可能会改变系统日期
即使只是短期的改变在某些环境下也是不允许的
即使允许也存在在日期临界点改变日期后恢复时可能存在错误

我现在常用的方法是net user
net user _ /expires:2004-02-29 2>&1|find "日期">nul&&echo 不合法的日期||echo 合法的日期
1

评分人数

天的白色影子

TOP

按照合法日期的模式排列了组合一下findstr的模式串
不考虑闰年计算是10条
[1-2][0-9][0-9][0-9]0[1-9]0[1-9]
[1-2][0-9][0-9][0-9]0[1-9]1[0-9]
[1-2][0-9][0-9][0-9]0[^2]2[0-9]
[1-2][0-9][0-9][0-9]022[0-8]
[1-2][0-9][0-9][0-9]0[13578]3[0-1]
[1-2][0-9][0-9][0-9]0[469]30
[1-2][0-9][0-9][0-9]1[0-2]0[1-9]
[1-2][0-9][0-9][0-9]1[0-2][12][0-9]
[1-2][0-9][0-9][0-9]1[02]3[0-1]
[1-2][0-9][0-9][0-9]1130

如果考虑闰年计算
需要增补XXXX0229的模式串
仅考虑被4整除是2条
[1-2][0-9][02468][048]0229
[1-2][0-9][13579][26]0229
加起来一共是12条

考虑100,400整除的情况稍微复杂些
需要将00从[02468][048]中排除
即将之拆分成[2468][048]和[02468][48]
[1-2][0-9][13579][26]0229
[1-2][0-9][2468][048]0229
[1-2][0-9][02468][48]0229
[02468][048]000229
[13579][26]000229
加起来一共15条

这是正向过滤合法日期的模式串
反向过滤非法日期的模式串应该稍微简单些
只是还未想到过滤掉长度非法的模式串
1

评分人数

    • zm900612: 好思路!第一个想到反向排除PB + 6
天的白色影子

TOP

本帖最后由 qzwqzw 于 2011-5-30 17:53 编辑

OK
感谢提醒
我的关于“正向、反向”的提法有问题
/v开关的“不包含匹配”用在正则中
实际上是指“任一模式串均不匹配”
使用/v开关后不需要改变模式串
也可以可通过逆变&&后面的程序逻辑得到相同的效果

我所说的反向应该是指模式串的“反向”
即正向模式串的逆变

正向确实是“符合任意一条都匹配”
我的正向模式串正体现了这一特性

^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$
是判定日期串长度合法而非非法的
虽然使用/v或者逆变程序逻辑
可以独立地判定字符串长度非法
但是无法与逆向模式串结合使用

我想了一下
关于逆向模式串长度非法只能使用
^$
^.$
^..$
^...$
^....$
^.....$
^......$
^.......$
^..........*$

结合其他逆向的模式
组建非法日期的模式串
[^0-9]
^[3-9]
00..$
1[3-9]..$
[2-9]...$
00$     
3[2-9]$
[4-9].$
0[469]31$
1131$
0230$
0229$

以上不考虑闰年计算的
考虑闰年需要将最后一条替换成
[13579]0229$
[13579][048]0229$
[02468][26]0229$
[13579]000229$
[13579][048]000229$
[02468][26]000229$
天的白色影子

TOP

本帖最后由 qzwqzw 于 2011-5-30 20:08 编辑

以下是正、逆模式的测试代码
请各位检阅
  1. @echo off & setlocal
  2. set 正模式=
  3. set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[1-9]0[1-9]$"
  4. set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[1-9]1[0-9]$"
  5. set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[^02]2[0-9]$"
  6. set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]022[0-8]$"
  7. set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[13578]3[0-1]$"
  8. set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[469]30$"
  9. set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]1[0-2]0[1-9]$"
  10. set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]1[0-2][12][0-9]$"
  11. set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]1[02]3[0-1]$"
  12. set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]1130$"
  13. set "正模式=%正模式% ^[1-2][0-9][13579][26]0229$"
  14. set "正模式=%正模式% ^[1-2][0-9][2468][048]0229$"
  15. set "正模式=%正模式% ^[1-2][0-9][02468][48]0229$"
  16. set "正模式=%正模式% ^[02468][048]000229$"
  17. set "正模式=%正模式% ^[13579][26]000229$"
  18. set 正模式
  19. echo.
  20. set 逆模式=
  21. set "逆模式=%逆模式% ^$"
  22. set "逆模式=%逆模式% ^.$"
  23. set "逆模式=%逆模式% ^..$"
  24. set "逆模式=%逆模式% ^...$"
  25. set "逆模式=%逆模式% ^....$"
  26. set "逆模式=%逆模式% ^.....$"
  27. set "逆模式=%逆模式% ^......$"
  28. set "逆模式=%逆模式% ^.......$"
  29. set "逆模式=%逆模式% ^..........*$"
  30. set "逆模式=%逆模式% [^0-9]"
  31. set "逆模式=%逆模式% ^[3-9]"
  32. set "逆模式=%逆模式% 00..$"
  33. set "逆模式=%逆模式% 1[3-9]..$"
  34. set "逆模式=%逆模式% [2-9]...$"
  35. set "逆模式=%逆模式% 00$"
  36. set "逆模式=%逆模式% 3[2-9]$"
  37. set "逆模式=%逆模式% [4-9].$"
  38. set "逆模式=%逆模式% 0[469]31$"
  39. set "逆模式=%逆模式% 1131$"
  40. set "逆模式=%逆模式% 0230$"
  41. set "逆模式=%逆模式% [13579]0229$"
  42. set "逆模式=%逆模式% [13579][048]0229$"
  43. set "逆模式=%逆模式% [02468][26]0229$"
  44. set "逆模式=%逆模式% [13579]000229$"
  45. set "逆模式=%逆模式% [13579][048]000229$"
  46. set "逆模式=%逆模式% [02468][26]000229$
  47. set 逆模式
  48. echo.
  49. :loop
  50. set /p 输入值=按yyyymmdd格式输入日期,输入Q退出:
  51. if /i "%输入值%"=="q" goto :eof
  52. rem 去除输入串前后的空格
  53. for %%v in (%输入值%) do set 输入值=%%v
  54. echo.%输入值%|findstr "%正模式%">nul && set 正结果=合法|| set 正结果=非法
  55. echo 正模式匹配后:'%输入值%'是%正结果%的日期
  56. echo.
  57. echo.%输入值%|findstr "%逆模式%">nul && set 逆结果=非法|| set 逆结果=合法
  58. echo 逆模式匹配后:'%输入值%'是%逆结果%的日期
  59. echo.
  60. goto :loop
复制代码
1

评分人数

    • batman: 思路总是那么相似PB + 10
天的白色影子

TOP

是的特意没有判断3000年
感觉没有什么意义
如果扩展的话
可以直接简单扩展到0000~9999

32楼的正则模式串
可以将10以上月份的10~29合并匹配

感觉/x没有办法适应逆模式下的非法长度判定
不可有何扩展的思路
天的白色影子

TOP

修订了正模式中的非2月的20~29匹配模式
比如如下的值正模式判断出错
20010020

set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[^2]2[0-9]$"
改为
set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[^02]2[0-9]$"
天的白色影子

TOP

刚才思考了一下
使用单条set应该也可以实现日期的合法性检查
有兴趣的可以贴一下的自己的方案
要求与楼主的大致相同
只是除了变换一下命令主体
天的白色影子

TOP

贴一下单条set的方案
利用了很多Set/a的错误检测特性
_%输入值%=1%输入值%
::利用运算符不存在检测判断输入值是否全数字
1/(年/1000) 和 1/(3000/年)
::利用被0除错误检测输入值中的年份是否1000<=年<=3000
%输入值:~7%/(9/1%输入值:~8%)
::利用运算符不存在和被0除错误检测输入值长度是否等于8
诸如此类
  1. @echo off & setlocal
  2. :loop
  3. set /p 输入值=按yyyymmdd格式输入日期,输入Q退出:
  4. if /i "%输入值%"=="q" goto :eof
  5. rem 去除输入串前后的空格
  6. for %%v in (%输入值%) do set 输入值=%%v
  7. 2>nul set /a "_%输入值%=1%输入值%,%输入值:~7%/(9/1%输入值:~8%),年=1%输入值:~0,4%-10000,月=1%输入值:~4,2%-100,日=1%输入值:~6,2%-100,大月=!((月-1)*(月-3)*(月-5)*(月-7)*(月-8)*(月-10)*(月-12)),闰年=!(年%%4)&!(!(年%%100))|!(年%%400),1/((年/1000)*(3000/年)*(月/1)*(12/月)*(日/1)*(31/日)*(!(日/31)|大月)*(!(日/30)|(月-2))*(!(日/29)|(月-2)|闰年))"&&set 结果=合法||set 结果=非法
  8. echo set/a检测'%输入值%'的结果:%结果%的日期
  9. echo.
  10. goto :loop
  11. pause
复制代码
1

评分人数

天的白色影子

TOP

返回列表