[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
本帖最后由 buyiyang 于 2024-8-24 17:47 编辑

回复 45# aloha20200628
1//1a
1/--1
1/+1
一个是分隔符被忽略的问题,一个是if比较时不能转换成有效数字的会按字符比较,数字比较时没有排除正负号。
忘了还有变量延迟下的两个特殊字符,
1/!1
1/!^1

TOP

本帖最后由 aloha20200628 于 2024-8-24 23:07 编辑


再练一把 ‘纯P进行到底’ 的脑力操...
给一个纯P版本的日期输入合法性检查代码,不用外部方法,不用正则匹配
算法简明得益于采用 ‘字典变量’,尽可能考虑了各种防错对策》分隔符及其错位,日月数值溢出,日月相关,平闰年天数区分... 还是回归日月均为两位数的要求。
以下代码采用循环输入以便完成各种测试,直至空回车退出...
  1. @echo off &setlocal
  2. set/a "_1=31,_2=28,_3=31,_4=30,_5=31,_6=30,_7=31,_8=31,_9=30,_10=31,_11=30,_12=31,y=%date:~,4%%%4"
  3. if %y% equ 0 set "_2=29"
  4. :[md_loop]
  5. set "md=" &set "c=" &set/p "md=输入日期(月值/日值):"
  6. if not defined md endlocal&exit/b
  7. setlocal enabledelayedexpansion &set k=!md:"=!
  8. if "!k!" neq "!md!" echo,非法&endlocal&goto[md_loop]
  9. endlocal &if "%md:~5%" neq "" echo,非法&goto[md_loop]
  10. if "%md:~4,1%"=="" echo,非法&goto[md_loop]
  11. for /f "tokens=1,2 delims=/" %%1 in ("%md%") do set "m=%%1"&set "d=%%2"
  12. if "%md%"=="%m%" echo,非法&goto[md_loop]
  13. for /f "delims=0123456789" %%n in ("%m%%d%") do set "c=1"
  14. if defined c echo,非法&goto[md_loop]
  15. if not defined d echo,非法&goto[md_loop]
  16. if "%md:~2,1%" neq "/" echo,非法&goto[md_loop]
  17. if "%m:~0,1%" equ "0" if "%m:~1,1%" neq "" set "m=%m:~1%"
  18. set "_m=_%m%" &set "w=非法" &setlocal enabledelayedexpansion
  19. if "%d:~0,1%" equ "0" if "%d:~1,1%" neq "" set "d=%d:~1%"
  20. if %d% gtr 0 if %d% leq !%_m%! set "w=合法"
  21. echo,!w!&endlocal&goto[md_loop]
复制代码
1

评分人数

    • 77七: 感谢分享技术 + 1

TOP

回复 36# buyiyang
细致!严谨!

TOP

回复 37# 77七


    感谢测试,限制上限的时候忘记限制下限了,再补上 set /a "1/(!!mm&!!dd)" 2>nul ||(%error%) 就没有问题了。

TOP

本帖最后由 qixiaobin0715 于 2024-8-22 12:48 编辑

仔细的研究了findstr命令的一般表达式,确实功能极其有限,相当于极简版的正则。有点手痒痒,也来一个吧。匹配原则:先多后少,先一般后特殊。
  1. findstr /x "0[1-9]/[0-2][1-9] 1[0-2]/[0-2][1-9] 0[1-9]/[12]0 1[0-2]/[12]0 0[13-9]/30 1[0-2]/30 0[13578]/31 1[02]/31"
复制代码
表达式说明:
0[1-9]/[0-2][1-9]    ——    1、2组对应所有月份,日期在30以内的组合,不包括日期10、20、30,因为不易避开非法日期00,还是单独处理为好;
1[0-2]/[0-2][1-9]
0[1-9]/[12]0           ——    3、4组单独处理上面所说的未包括的日期10、20,也是对应所有月份;
1[0-2]/[12]0
0[13-9]/30              ——    5、6组对应日期为30的月份,2月除外;
1[0-2]/30
0[13578]/31            ——    最后2组对应日期为31的月份,包括1、3、5、7、8、10、12月;
1[02]/31
欢迎大家批评指正。

TOP

本帖最后由 aloha20200628 于 2024-8-22 11:19 编辑


即便是批处这类简单脚本级的造码,也是讲究 ‘有效 》可靠 》高效 》简洁’ 四重关,新手过头关,老手要高攀,若每次出手都能 ‘会当凌绝顶’,真可谓功德圆满了... 共勉共勉

TOP

用临时文件,仅判断两位数+/+两位数,应该可以对付所有特殊字符了吧
  1. @echo off
  2. set /p str=input:
  3. setlocal enabledelayedexpansion
  4. >1.txt echo=#!str!
  5. endlocal
  6. findstr /rxc:"#[0-9][0-9]/[0-9][0-9]" 1.txt
  7. if not errorlevel 1 (
  8. echo ok
  9. )
  10. pause
复制代码
bat小白,请多指教!谢谢!

TOP

回复 31# 77七
私下试了一把,全定义确实省事。

TOP

本帖最后由 qixiaobin0715 于 2024-8-22 09:07 编辑

回复 34# WHY
我也知道这么一个问题,用cmd搞出如此复杂的代码,确实不合适。
开始看到这个帖子,主要是想籍此私下练习练习逻辑思维,等到着手写代码时,没想到会是这么复杂,自己心里没底,发出来让大家看看 ,真是漏洞百出,最后重写代码,还是有漏洞。
最后的代码是借鉴27楼的建议重写的,发上来前,在13行下面有一行代码,是用来判断第3个字符是否为“/”的,个人感觉后续代码能够处理此问题,就给删除了,看来还是有用的,最少能够修补你在33楼所说的漏洞。
还是要在29楼第13、14行之间,加上删除的那行代码:
  1. if not "%md:~2,1%"=="/" goto :p
复制代码

TOP

回复 35# buyiyang


   
大佬,00/00的情况,没有判断,防不胜防
bat小白,请多指教!谢谢!

TOP

回复 27# aloha20200628


    因为09不是有效的八进制数字,试试0x9
1

评分人数

    • qixiaobin0715: 像我这样的大多数人都会忽略这个问题!技术 + 1

TOP

才5个字符,用批处理的话逐字符判断更可靠一些
  1. @echo off
  2. set/p "data=Please enter a date (MM/DD):"
  3. set "error=echo,Invalid date&pause&goto :eof"
  4. setlocal enabledelayedexpansion
  5. for /l %%i in (5,-1,0) do (
  6.     set "data%%i=!data:~%%i,1!"
  7.     if not "!data%%i!"=="" (
  8.         if %%i equ 5 (
  9.             %error%
  10.         ) else if %%i equ 2 (
  11.             if "!data%%i!" neq "/" %error%
  12.         ) else if "!data%%i!" lss "0" (
  13.             %error%
  14.         ) else if "!data%%i!" gtr "9" %error%
  15.     ) else (
  16.         if %%i equ 4 %error%
  17.     )
  18. )
  19. if %data0% equ 0 set "data0="
  20. if %data3% equ 0 set "data3="
  21. set mm=%data0%%data1%
  22. set dd=%data3%%data4%
  23. if %mm% gtr 12 %error%
  24. if %dd% gtr 31 %error%
  25. for /f "tokens=2" %%i in ('wmic os get codeset^,localdatetime') do (
  26.     set yyyy=%%i
  27.     set "yyyy=!yyyy:~0,4!"
  28.     )
  29. endlocal&set /a mm=%mm%,dd=%dd%,yyyy=%yyyy%
  30. set /a "gtm=!(mm-4)|!(mm-6)|!(mm-9)|!(mm-11)","leap=!(yyyy%%4)&!!(yyyy%%100)|!(yyyy%%400)","dlim=!(mm-2)*(28+leap)+gtm*30+(!!(mm-2)&!gtm)*31"
  31. if %dd% gtr %dlim% (%error%) else (echo,Valid date)
  32. pause&exit /b
复制代码
1

评分人数

    • 77七: 学习了,set/a很精彩!技术 + 1

TOP

个人观点:特殊字符是 CMD 的硬伤,用纯P来解此题,简直就是自找麻烦。
吐槽一下:“你认为有前途的,其他人或许认为就是辣鸡”,事实证明这句话是对的。

TOP

本帖最后由 WHY 于 2024-8-21 21:25 编辑

回复 29# qixiaobin0715


    还要考虑一下,分隔符位于字符串开头的情况, for /f 会去掉字符串开头的分隔符。
比如输入:/03/12

TOP

本帖最后由 qixiaobin0715 于 2024-8-21 16:29 编辑

回复 31# 77七
想过,代码会缩减很多。但变量定义过多(至少366个),会影响效率。
上面说过了,主要是练练手。

TOP

返回列表