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

回复 1# 蚯蚓传奇

以下代码存为 test.bat 运行...
备注》powershell兼容 ‘月/日’ 和 ‘月-日’ 多种格式分隔符,自动检查月日合法性(尤其是2月日期)
  1. @echo off &set/p "_md=输入日期(月值/日值):"
  2. for /f %%v in (
  3. 'powershell "('2024/%_md%' -as [DateTime]) -ne $null" '
  4. ) do if /i "%%v"=="true" (echo,输入合法) else (echo,输入非法)
  5. pause&exit/b
复制代码
1

评分人数

TOP

本帖最后由 aloha20200628 于 2024-8-19 21:10 编辑

回复 3# 蚯蚓传奇

增添子过程 :xxx 用于检查日期输入格式是否满足 mm/dd,分隔符须为 /,mm 和 dd 都必须是两位数字...
  1. @echo off &setlocal &set/p "md=输入日期(月值/日值):"
  2. call :xxx "%md%"
  3. if %ok% equ 0 (echo,输入非法)&exit/b
  4. for /f %%v in (
  5. 'powershell "('2024/%md%' -as [DateTime]) -ne $null" '
  6. ) do if /i "%%v"=="true" (echo,输入合法) else (echo,输入非法)
  7. endlocal&pause&exit/b
  8. :xxx
  9. set "v=%~1" &set "ok=0" &set "n="
  10. if "%v:~4,1%" neq "" if "%v:~5%"=="" (
  11. for /f "delims=0123456789/" %%n in ("%~1") do set "n=1"
  12. if not defined n set "ok=1"
  13. )
  14. exit/b
复制代码
1

评分人数

TOP

本帖最后由 aloha20200628 于 2024-8-24 22:32 编辑


参考6楼代码用 findstr 小正则卡位定界 mm/dd 格式输入,句式更为简洁,如此4楼代码可减肥‘到底’ ,给出如下两个等效版本...

第一版本》先行正则卡位定界,再行powershell合法性检查
  1. @echo off &setlocal &set/p "md=输入日期(月值/日值):"
  2. echo,%md%|findstr /rc:"[01][0-9]/[0-3][0-9]">nul||echo,非法&endlocal&pause&exit/b
  3. powershell "('2024/%md%' -as [DateTime]) -ne $null"|find /i "true">nul
  4. if errorlevel 1 (echo,非法) else (echo,合法)
  5. endlocal&pause&exit/b
复制代码
第二版本》先行powershell合法性检查,再行卡位定界
  1. @echo off &setlocal &set "w=非法" &set/p "md=输入日期(月值/日值):"
  2. powershell "('2024/%md%' -as [DateTime]) -ne $null"|find /i "true">nul
  3. if errorlevel 1 (set k=1) else if "%md:~2,1%"=="/" if "%md:~-3,1%"=="/" set "w=合法"
  4. echo,%w%&endlocal&pause&exit/b
复制代码

TOP

本帖最后由 aloha20200628 于 2024-8-20 17:06 编辑

回复 10# 77七

‘纯P老窖’ 还留了一款  set/p="..."<nul  此时正好派上用场...
echo,"..." 连双引号一并输出;而 set/p="..."<nul 只输出双引号包裹的内容,但先戴上双引号即可免遭 ‘雷劈’
  1. set/p="1&2"<nul|find "1">nul&&echo,#1
  2. set/p="1&2"<nul|find "2">nul&&echo,#2
复制代码

TOP

回复 6# ppll2030
回复 9# 蚯蚓传奇

网查用正则匹配(同时也是检查)日期格式有多种杂乱版本,实测了一把6楼代码,发现有一处须予订正如下,否则会漏检 10/00,11/00,12/00 的错误:

   旧码》findstr /x "0[1-9]/0[1-9] 0[1-9]/[1-2][0-9] 0[13578]/3[0-1] 0[469]/30 1[0-2]/0[0-9] 1[0-2]/[1-2][0-9] 1[02]/3[0-1] 11/30"
   新码》findstr /x "0[1-9]/0[1-9] 0[1-9]/[1-2][0-9] 0[13578]/3[0-1] 0[469]/30 1[0-2]/0[1-9] 1[0-2]/[1-2][0-9] 1[02]/3[0-1] 11/30"

另注》仅用正则匹配不能兼顾平/闰年2月增减天数的变化,还须增添代码修正...

TOP

回复 19# qixiaobin0715

用纯P一贯到底,还是应该先解决 ‘卡位和定界’,即检查输入长度是否=5,检查第三位是否为 /,检查定界符之外是否均为数字,其后再完成月值与日值的关联处理,否则会使处理逻辑复杂化...

另说》纯P内部数据处理也许只有字符串一种数据类型,因此以下三式返回值相同
   if 09 lss 1 (@echo,1) else @echo,0
   if "09" lss "1" (@echo,1) else @echo,0
   if 0q lss 1 (@echo,1) else @echo,0
1

评分人数

TOP

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


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

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

本帖最后由 aloha20200628 于 2024-8-24 19:46 编辑

回复 46# buyiyang

45楼代码已订正,堵上了被多种 ‘怪异字符’ 轰击破防的缺口...

本帖歇后语》不用外部方法援助,不用正则匹配简化,感觉纯P自力更生的造码能力还可以...而真正的着力点落在了应对预处理和防止怪异字符的雷劈...

TOP

本帖最后由 aloha20200628 于 2024-8-24 21:02 编辑

回复 50# buyiyang
谢谢细心测试 45楼代码已被订正...
要纯P到底,那些 卡位,定界,全数字核查... 一点懒儿都不能偷

TOP

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

回复 53# 77七

谢谢 代码已订正... 但愿是最后一把 ‘堵漏灵’...
从8楼调用 powershell+findstr 外援的4-5行代码到45楼的纯P自力更生版,已经垒起21行代码了,要经得起各种怪异字符的 ‘雷劈’ ... 纯粹是要过把瘾的一套脑力操...

TOP

本帖最后由 aloha20200628 于 2024-8-25 16:18 编辑


精简了45楼代码中的操作步骤和合法性核查逻辑,行数减至18行,8个goto减至2个...
操作步骤要点》
   双引号排查
   输入长度排查
   定界符及其错位排查
   日月值全数字排查
   日月相关变化所对应的字典变量 以及 平闰年天数增减修正
   全程严防 &!"^ 等特殊字符雷劈的对策...
再次感谢各位细心测试反馈 就算是一场把纯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 #md=!$md:"=!
  8. if "!#md!"=="!$md!" if "!$md:~5!"=="" if "!$md:~4,1!" neq "" if "!$md:~2,1!"=="/" (
  9. set "m=!$md:~0,2!"&set "d=!$md:~3!"
  10. for /f "delims=0123456789/" %%n in ("!$md!") do set "c=1"
  11. if not defined c goto[ok] )
  12. echo,非法&endlocal&goto[md_loop]
  13. :[ok]
  14. if "!m:~0,1!" equ "0" set "m=!m:~1!"
  15. set "_m=_!m!" &set "w=非法"
  16. if "!d:~0,1!" equ "0" set "d=!d:~1!"
  17. if !d! gtr 0 if !d! leq !%_m%! set "w=合法"
  18. echo,!w!&endlocal&goto[md_loop]
复制代码

TOP


批处是一种典型的解译型脚本,其执行原理基本上就是逐行处理(连注释行也不放过),也许对复合语块要先全块读尽再逐行处理,因此代码能并为一行会比分行的解译执行效率高,此被老帖早有述及,但这同时也会降低代码可读性... 总而言之,这是一个二者权衡尺度的问题,又是一个造码者编程风格或言个人偏好的问题...

TOP

本帖最后由 aloha20200628 于 2024-8-26 18:30 编辑

回复 68# 77七

已说过也许批处对复合语块典型如for...句式是先全块读尽处理的,此乃for句式效率较高的原因,其内是不能如其外简单分行执行的...
与解译型脚本逐行解译执行原理一致的纯净测试应该如是:
   set a=...&set b=...&...

  set a=...
  set b=...
  ...
比对测试
但对批处的小微代码测试而言,其差别也许无感...

TOP

返回列表