Board logo

标题: [数值计算] 批处理怎么去除一个固定关系的行? [打印本页]

作者: ads350668398    时间: 2019-5-4 20:39     标题: 批处理怎么去除一个固定关系的行?

1.txt
01 02 03 04 05
01 02 03 04 06
01 02 03 04 07
01 02 03 04 08
01 02 03 04 09
01 02 03 04 10
01 02 03 04 11

怎么用一个表达式排除如 %b=%a+1 c%=%b+1 %d=%c+1 %e=%d+1
也就是12345这样的行 23456也是 符合的
应该%b=%a*2 %c=%b*2 %d=%c*2 。。。。
2 4 6 8 10
作者: ads350668398    时间: 2019-5-4 20:54

每次登陆提出问题 也是厚着脸皮 F5 F5 的刷新等着论坛里的大神帮忙
对于一个10年注册的老鸟了吧的尴尬
对于论坛给过我帮助的网友 无以为报 只有诚挚的祝福
作者: Batcher    时间: 2019-5-4 22:20

顶楼的 1.txt 处理之后应该变成什么样子?
作者: Batcher    时间: 2019-5-4 22:35

是这个意思吗?
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. (for /f "tokens=1-5" %%a in ('type "1.txt"') do (
  4.     set flag=0
  5.     set /a sum1=%%a+1
  6.     set /a sum2=%%b+1
  7.     set /a sum3=%%c+1
  8.     set /a sum4=%%d+1
  9.     if %%b equ !sum1! (
  10.         set /a flag+=1
  11.     )
  12.     if %%c equ !sum2! (
  13.         set /a flag+=1
  14.     )
  15.     if %%d equ !sum3! (
  16.         set /a flag+=1
  17.     )
  18.     if %%e equ !sum4! (
  19.         set /a flag+=1
  20.     )
  21.     if !flag! neq 4 (
  22.         echo %%a %%b %%c %%d %%e
  23.     )
  24. ))>"2.txt"
复制代码

作者: ads350668398    时间: 2019-5-4 23:24

回复 2# ads350668398

【排除12345】谢谢关注
01 02 03 04 06
01 02 03 04 07
01 02 03 04 08
01 02 03 04 09
01 02 03 04 10
01 02 03 04 11
作者: xczxczxcz    时间: 2019-5-4 23:29

本帖最后由 xczxczxcz 于 2019-5-7 17:25 编辑

回复 5# ads350668398

来个通用点的。powershell
  1. powershell
复制代码

作者: ads350668398    时间: 2019-5-4 23:37

升级版的bat 谢谢关注了
作者: ads350668398    时间: 2019-5-5 08:08

回复 4# Batcher


奇数-=~%%a%%2
,#偶数+=%%a%%2,
#被三整除+=%%a%%3,
#和+=100,
可以不可以吧这些关系的数字也删除啊??
例如

5 9 13 21 33奇数
2 12 26 28 32 偶数
3 9 18 27 33 北三整除
作者: Batcher    时间: 2019-5-5 12:18

回复 8# ads350668398


    我看不懂这些关系表示什么意思。你自己修改一下4楼的代码,把你想要的计算和判断放进去试试,遇到具体问题再回来问。
作者: ads350668398    时间: 2019-5-5 21:14

回复 9# Batcher


01 02 03 04 05 连续1
01 02 03 04 06
01 02 03 04 07
01 02 03 04 08
01 02 03 04 09
01 02 03 04 10
01 02 03 04 11
02 03 04 05 06 连续2
02 04 06 08 10 偶数0
03 06 09 12 15
01 03 05 07 09 奇数1
05 10 15 20 25 整除5
06 09 15 27 33 整除3
01 04 07 10 13
01 05 09 13 17 奇数2
01 06 11 16 21
01 07 13 19 25 奇数3
01 08 15 22 29
01 09 18 26 34
03 11 15 21 23 奇数4
06 10 18 22 28 偶数1
04 06 08 10 12 偶2
06 07 08 09 10 连续3
23 24 25 26 27 连续4
06 10 20 22 28 偶数3
28 29 30 31 32 连续5

我是打算去除这些连续1 2 3 4 5和奇数1 2 3 4 偶数1 2 3
现在连续和偶数基本解决了 虽然很。。。
怎么去除奇数 想不出来了??? 还有被3 5 整除????

------------------------
set flag=0
    set /a sum1=%%a+1
    set /a sum2=%%b+1
    set /a sum3=%%c+1
    set /a sum4=%%d+1
    if %%b equ !sum1! (
        set /a flag+=1
    )
    if %%c equ !sum2! (
        set /a flag+=1
    )
    if %%d equ !sum3! (
        set /a flag+=1
    )
    if %%e equ !sum4! (
        set /a flag+=1
    )
    if !flag! neq 4 (
        echo %%a %%b %%c %%d %%e %%f
可能都不知道我说的是什么但是
06 07 08 09 10 连续 3  失败
这一行在运行的时候也处理不掉 我知道是不是我电脑的毛病啊
******************************
(for /f "tokens=1-28" %%a in ('type "1.txt"') do (
    set flag=0
    set /a sum1=%%a+2
    set /a sum2=%%b+2
    set /a sum3=%%c+2
    set /a sum4=%%d+2
    if %%b equ !sum1! (
        set /a flag+=2
    )
    if %%c equ !sum2! (
        set /a flag+=2
    )
    if %%d equ !sum3! (
        set /a flag+=2
    )
    if %%e equ !sum4! (
        set /a flag+=2
    )
    if !flag! neq 4 (
        echo %%a %%b %%c %%d %%e %%f
    )
))>"2.txt"
set s
set sum1
set sum2
set sum3
set sum4
echo !%a%! %%b %%c %%d %%e
start 2.txt
::ping /n 8 127.0.0.1<nul
taskkill /im 2.txt
pause
结果:
02 04 06 08 10 偶数0 成功
06 10 18 22 28 偶数1 失败
04 06 08 10 12 偶2    成功
06 10 20 22 28 偶数3 失败
作者: Batcher    时间: 2019-5-7 15:17

06 07 08 09 10 连续 3  失败

修复这个bug你试试:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. (for /f "tokens=1-5" %%a in ('type "1.txt"') do (
  4.     set flag=0
  5.     set /a sum1=1%%a+1
  6.     set /a sum2=1%%b+1
  7.     set /a sum3=1%%c+1
  8.     set /a sum4=1%%d+1
  9.     if 1%%b equ !sum1! (
  10.         set /a flag+=1
  11.     )
  12.     if 1%%c equ !sum2! (
  13.         set /a flag+=1
  14.     )
  15.     if 1%%d equ !sum3! (
  16.         set /a flag+=1
  17.     )
  18.     if 1%%e equ !sum4! (
  19.         set /a flag+=1
  20.     )
  21.     if !flag! neq 4 (
  22.         echo %%a %%b %%c %%d %%e
  23.     )
  24. ))>"2.txt"
复制代码

作者: ads350668398    时间: 2019-5-26 08:46

怎么去除奇数 北三被5 我一头雾水 穷尽。。。。
作者: ivor    时间: 2019-5-26 12:12

本帖最后由 ivor 于 2019-5-30 07:56 编辑
  1. @Powershell "& {[ScriptBlock]::Create("'#' + (gc '%~f0' -raw)").Invoke()}" & pause & goto :eof
  2. gc 1.txt | %{[int[]]$arr=$_ -split ' ';
  3. # 过滤递增1
  4. if(!(($arr[0] + 1 -eq $arr[1]) -and ($arr[1] + 1 -eq $arr[2])-and ($arr[2] + 1 -eq $arr[3])-and ($arr[3] + 1 -eq $arr[4]))) {
  5.     # 过滤递增2
  6.     if(!(($arr[0] + 2 -eq $arr[1]) -and ($arr[1] + 2 -eq $arr[2])-and ($arr[2] + 2 -eq $arr[3])-and ($arr[3] + 2 -eq $arr[4]))) {
  7.         # 过滤整除5
  8.         if(!(($arr[0] % 5  -eq 0) -and ($arr[1] % 5  -eq 0)-and ($arr[2] % 5  -eq 0)-and ($arr[3] % 5  -eq 0)-and ($arr[4] % 5  -eq 0))) {
  9.             # 过滤整除3
  10.             if(!(($arr[0] % 3  -eq 0) -and ($arr[1] % 3  -eq 0)-and ($arr[2] % 3  -eq 0)-and ($arr[3] % 3  -eq 0)-and ($arr[4] % 3  -eq 0))) {
  11.                 write $_
  12.             }
  13.         }   
  14.     }
  15. }
  16. }
复制代码

作者: xczxczxcz    时间: 2019-5-26 20:49

回复 13# ivor


      用FOR 不是又快又简?如果楼上的数据列数加减变化那不惨了。不过最大可能楼上是用BAT 。不会考虑PS。
作者: amwfjhh    时间: 2019-5-26 21:58

要是规则比较多的话可以试着建一个规则文件来读取,然后批处理里面来解释规则库,然后逐行测试……
作者: ads350668398    时间: 2019-5-27 15:06

回复 13# ivor


    升级的bat 是的
但是这个好比别的语言 复杂难以理解 执行结果

C:\Users\Administrator\Desktop>owershell "& {[ScriptBlock]::Create("'#' + (gc '
C:\Users\Administrator\Desktop\1除以3的余数.bat' -raw)").Invoke()}"   & pause
& goto :eof
Get-Content : 找不到与参数名称“raw”匹配的参数。
所在位置 行:1 字符: 85
+ & {[ScriptBlock]::Create('#' + (gc 'C:\Users\Administrator\Desktop\1除以3的余
数.bat' -raw <<<< )).Invoke()}
    + CategoryInfo          : InvalidArgument: ( [Get-Content], ParameterBin
   dingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Comm
   ands.GetContentCommand

请按任意键继续. . .
作者: 老刘1号    时间: 2019-5-27 23:38

批处理的各种奇诡用法才是复杂难以理解的吧……
作者: hongrk    时间: 2019-5-29 23:49

本帖最后由 hongrk 于 2019-5-30 18:46 编辑

回复 8# ads350668398

经测试可用。添加其他规则方法类似,如果很多的话可以再套一个for循环
  1. @echo off
  2. (for /f "tokens=*" %%a in (1.txt)do (
  3.   set/a js=os=fs=0
  4.   for %%i in (%%a)do (
  5.      2>nul set/a1/(1%%i"&"1^)&&set/a js+=1||set/a os+=1
  6.      rem 添1防当成八进制
  7.      rem 数是奇数则js+1,偶数同理。最后js=0则说明全偶,os=0则说明全奇。
  8.      2>nul set/a1/(3%%i%%3^)&&set/a fs+=1
  9.      rem 最后fs[非三]=0则说明全是3的倍数。
  10.      )
  11.   2>nul set/a1/(js*os*fs^)&&echo %%a
  12.      rem 只要有1个为0就不会回显
  13. ))>"2.txt"
复制代码

作者: hongrk    时间: 2019-5-29 23:51

回复 17# 老刘1号


    赞成,排BUG有时候最后排出来是真的气……自己感觉语法没问题,但就是会报错,还得把踩雷的写法记下来不能犯,非常憋屈。
作者: Batcher    时间: 2019-5-30 08:56

回复 18# hongrk


    你测试的我哪个代码?bat文件和txt文件打包压缩传上来我试试
作者: hongrk    时间: 2019-5-30 18:48

回复 20# Batcher


    我已经找到原因了。用的是您在4楼发的代码,执行失败原因是我把它拖进cmd执行,直接双击是可以正常使用的。
我自己的代码也已经找到问题所在(set/a中的括号没有转义、注释用了::而不是rem)并修复了,并在之前的位置重新编辑了一下。
作者: amwfjhh    时间: 2019-5-31 02:44

1.txt
  1. 01 02 03 04 05
  2. 01 02 03 04 06
  3. 01 02 03 04 07
  4. 01 02 03 04 08
  5. 01 02 03 04 09
  6. 01 02 03 04 10
  7. 01 02 03 04 11
复制代码
rule.txt
  1. 5 b=a+1 c=b+1 d=c+1 e=d+1
  2. 5 b=a+1 c=b+1 d=c+1 e=d+2
复制代码
test.bat
  1. @if (0)==(0) echo off
  2. setlocal enabledelayedexpansion
  3. REM 读取文件内容
  4. for /f "tokens=*" %%i in ('type 1.txt') do (
  5. set "strLine=%%i"
  6. echo,Line data : !strLine!
  7. echo,
  8. set "bFit=1"
  9. call :_analysis
  10. if "!bFit!" EQU "0" (
  11. echo,不符算式规则...
  12. ) else (
  13. echo,符合算式规则...
  14. )
  15. pause
  16. )
  17. pause
  18. exit /b
  19. :_analysis
  20. (
  21. for /f "tokens=*" %%i in ('type rule.txt') do (
  22. echo,Rule data : %%i
  23. cscript -nologo -e:jscript %~s0 CheckAlgorithm "!strLine!" "%%i"
  24. for /f "tokens=*" %%a in ('cscript -nologo -e:jscript %~s0 CheckAlgorithm "!strLine!" "%%i"') do (
  25. REM echo,---analysis : %%a
  26. set "bFit=%%a"
  27. )
  28. REM echo,Analysis result : !bFit!
  29. REM 符合规则
  30. if "!bFit!" EQU "1" goto :EOF
  31. )
  32. goto :EOF
  33. )
  34. @end
  35. var func = WScript.Arguments(0);
  36. switch (func) {
  37. case "CheckAlgorithm":
  38. var strSrc = WScript.Arguments(1);
  39. var strAlg = WScript.Arguments(2);
  40. CheckAlgorithm(strSrc, strAlg);
  41. break;
  42. default:;
  43. }
  44. function GetColData(str, nCol) {
  45. //WScript.Echo("str is : " + str);
  46. //WScript.Echo("nCol : " + nCol);
  47. var nLen = str.split(" ").length;
  48. return nCol <= nLen ? 1 : 0;
  49. }
  50. function CheckAlgorithm(str1, str2) {
  51. /// 检测数据个数是否符合
  52. var strAlgs = str2.split(" ");
  53. WScript.Echo("strAlgs : " + strAlgs);
  54. var nCol = strAlgs[0];
  55. var nRet = GetColData(str1, nCol);
  56. if (!nRet) {
  57. WScript.Echo("0");
  58. return;
  59. }
  60. var nNums = str1.split(" ");
  61. WScript.Echo("nNums : " + nNums);
  62. /// 逐行对比算式是否符合
  63. for (var i=1; i<strAlgs.length; i++) {
  64. strAlgTmp = strAlgs[i];
  65. WScript.Echo("Check algorithm : " + strAlgTmp);
  66. var n1 = strAlgTmp.replace(/(\w)=.*/i, "$1");
  67. var n2 = strAlgTmp.replace(/.=(\w).*/i, "$1");
  68. var nP = strAlgTmp.replace(/.=.(.).*/i, "$1");
  69. var n3 = strAlgTmp.replace(/.=..(.*)/i, "$1");
  70. var strCodec = "";
  71. strCodec += parseInt(nNums[n1.toUpperCase().charCodeAt(0)-65]) + "==" + parseInt(nNums[n2.toUpperCase().charCodeAt(0)-65]) + nP + n3;
  72. WScript.Echo(strCodec);
  73. nRet = eval(strCodec);
  74. if (!nRet) {
  75. WScript.Echo("0");
  76. return;
  77. }
  78. }
  79. WScript.Echo(nRet ? 1 : 0);
  80. }
复制代码
初步实现简单自定义计算式规则效果。
Rule.txt内数据格式:
第一个数为匹配数据的个数,用来进行初筛不符合数据量的行;
第二个数据起为具体需要实现的算式,变量以a字母开始,匹配被筛数据的第一个值,b为第二个值,以此类推;
可简单识别+-*算式,/式需要额外写取整操作,目前只处理了b=a[+-*]n的情况;
更复杂的算式,需要对算式拆分重组验证作更细分的处理。
未优化代码。抛砖引玉。
作者: ads350668398    时间: 2019-5-31 08:34

本帖最后由 ads350668398 于 2019-5-31 08:36 编辑

。。。。。。。。。。。。
。。。。。。。
感谢网友热心 我们很优秀
作者: Taurus    时间: 2019-6-1 18:09

本帖最后由 Taurus 于 2019-6-1 18:55 编辑
回复  ads350668398

【排除12345】谢谢关注
01 02 03 04 06
01 02 03 04 07
01 02 03 04 08
01  ...
ads350668398 发表于 2019-5-4 23:24


我用A.B.C.D.E比喻五段數組
例如:
01 02 03 04 07
01=strA ,02=strB , 03=strC , 04=strD , 07=strE

如果數組排序的邏輯必然是 : E大於D , D大於C , C大於B , B大於A的話 (沒有[相同數目]、或者[負數]) , 那你 set /a nub=!E!-!D!-!C!-!B!-!A!   , 接著if "!nub!=4" echo yes , 如果是連續數目 , 減下去!nub!就必然是4了 , 否則!nub!就不是連續數目。

這樣沒了迴圈、效率就應較快了
=======================
偶数、 奇数
取str的最後一位數字、補上一個0、再除2 ; 答案最尾一位不是0就是奇数 , 否則是偶数

整除3也一樣 , 在str後補上一個0(原理是把他當成小數點後的位)、再除3 , 答案最尾一位不是0就不能整除 , 否則是能整除(原理是 , 不能整除才會出現小數點)
整除5 , 同上

!str:~-1,1!     顯示最後一個字的寫法
!str:~0,-1!    去掉最後一個字的寫法


路過 , 邊看邊答 , 就不寫代碼了 , 只幫忙想想思路上迴圈最少的方法
作者: Taurus    时间: 2019-6-3 07:06

易讀版:
  1. @echo off&setlocal enabledelayedexpansion
  2. del testinbathome.txt 2>nul>nul
  3. for /f "tokens=1,2,3,4,5 delims= " %%a in (1.txt) do (
  4.      set ORG=%%a %%b %%c %%d %%e
  5.      for  %%f in (!ORG!) do (
  6.           set /a looptime+=1
  7. ::去除字串左前的所有0
  8.           set /a var!looptime!=-11%%f+10%%f+1%%f
  9.      )
  10.      call :step !var1! !var2! !var3! !var4! !var5!
  11.      set looptime=
  12. )>>testinbathome.txt
  13. start testinbathome.txt
  14. <
  15. :step
  16. ::判斷是否順數 , 非順數才繼續嘗試整除
  17. set str=set/a nub=%5-%4+%4-%3+%3-%2+%2-%1
  18. for /f  %%i in ('!str!') do (
  19.      set /p=!ORG!  <nul
  20.      if "%%i" EQU "4" (
  21.           echo 連續的字串
  22.      ) else (
  23.           ::非連續的字串
  24.           call :step2 !var1! !var2! !var3! !var4! !var5!
  25.      )
  26.      goto :eof
  27. )
  28. :step2
  29. ::判斷數字能否全為2-9之倍數 , 和判斷奇偶數
  30. set str=%10 %20 %30 %40 %50
  31. ::for語句[2,3,5,9] 可切換成 [2,3,4,5,6,7,8,9] , 則變成判繼2至9的所有倍數
  32.      for %%Z in (2,3,5,9) do (
  33.      call :step3 %%Z
  34.      if "!about%%Z!" EQU "00000" (
  35.           set /p=整除於[%%Z]<nul
  36.           if "%%Z"=="2" (set /p=, 偶數字串 , <nul)
  37.           )else if "!about%%Z!%%Z" == "555552"  (set /p=奇數字串<nul))
  38.      )
  39. echo.
  40. goto :eof
  41. )
  42. :step3
  43. ::數字2-9通用的整除計算語句
  44.      for /f "tokens=1,2,3,4,5 delims= " %%i in ('echo !str!') do set/a A=%%i/%1 ,B=%%j/%1,C=%%k/%1,D=%%m/%1,E=%%l/%1&&set about%1=!A:~-1,1!!B:~-1,1!!C:~-1,1!!D:~-1,1!!E:~-1,1!
复制代码
精簡版:
  1. @echo off&setlocal enabledelayedexpansion
  2. del testinbathome.txt 2>nul>nul
  3. for /f "tokens=1,2,3,4,5 delims= " %%a in (1.txt) do (
  4.      set ORG=%%a %%b %%c %%d %%e
  5.      for  %%f in (!ORG!) do set /a looptime+=1&&set /a var!looptime!=-11%%f+10%%f+1%%f
  6.      set/a str=!var5!-!var4!+!var4!-!var3!+!var3!-!var2!+!var2!-!var1!
  7.      set /p=!ORG!  <nul
  8.      if "!str!" EQU "4" set /p=連續的字串<nul
  9.      for %%Z in [color=Red](2,3,4,5,6,7,8,9)[/color] do (
  10.           set/a A=!var1!0/%%Z ,B=!var2!0/%%Z,C=!var3!0/%%Z,D=!var5!0/%%Z,E=!var5!0/%%Z
  11.           set about%%Z=!A:~-1,1!!B:~-1,1!!C:~-1,1!!D:~-1,1!!E:~-1,1!
  12.           if "!about%%Z!%%Z" == "555552" set mark=1&&set /p=奇數字串<nul
  13.           if "!about%%Z!" EQU "00000" (
  14.                if "%%Z"=="2" (
  15.                     set mark=2&set /p=偶數字串 , [%%Z]<nul
  16.                ) else (
  17.                     if !mark!==1 set /p=, <nul
  18.                     set mark=2&set /p=[%%Z]<nul
  19.                )
  20.           )
  21.           if !mark!9==2%%Z set /p=之倍數<nul
  22.      )
  23. echo.
  24. set looptime=&set mark=0
  25. )>>testinbathome.txt
  26. start testinbathome.txt
复制代码
測試文件[1.txt]
  1. 01 02 03 04 05
  2. 01 02 03 04 06
  3. 01 02 03 04 07
  4. 01 02 03 04 08
  5. 01 02 03 04 09
  6. 01 02 03 04 10
  7. 01 02 03 04 11
  8. 02 03 04 05 06
  9. 02 04 06 08 10
  10. 03 06 09 12 15
  11. 01 03 05 07 09
  12. 05 10 15 20 25
  13. 06 09 15 27 33
  14. 01 04 07 10 13
  15. 01 05 09 13 17
  16. 01 06 11 16 21
  17. 01 07 13 19 25
  18. 01 08 15 22 29
  19. 01 09 18 26 34
  20. 03 11 15 21 23
  21. 06 10 18 22 28
  22. 04 06 08 10 12
  23. 06 07 08 09 10
  24. 23 24 25 26 27
  25. 06 10 20 22 28
  26. 28 29 30 31 32
  27. 09 18 27 36 99
  28. 099 0117 0234 0594 07992
  29. 0090 0099 0909 0594 07992
  30. 02889 2898 02997 03789 04293
  31. 0029 030 00031 32 033
  32. 29 00030 031 00000032 0033
  33. 2 0000004 006 00008 10
  34. 550 00660 000770 880 0990
  35. 33 39 63 69 99
  36. 44 88 124 164 204
  37. 40 80 120 160 200
  38. 06 12 18 24 30
  39. 07 14 21 28 35
  40. 08 16 24 32 40
  41. 01 03 06 07 09
  42. 09 18 27 36 99
复制代码
我把他直接寫成可分類 : 奇數、偶數、順序字串、和分辨[1-9]的倍數
另外因不肯定你只是用來處理2位數組 , 也不肯定數目前必然只有1個零 , 所以也把它寫成可以通用處理[測試文件]那些古怪格式了
另外也因不肯定你只是用來處理[3]和[5]的倍數 , 所以也把它寫成可以通用分辨[1-9]的倍數。如果需要改回只處理3和5的倍數 , 你可把[精簡版:](2,3,4,5,6,7,8,9) 一句改成(2,3,5)就可以了

第一個[易讀版:]的代碼是方便你讀和修改的 , 所以盡量把運作分類和每部份寫註解了。如果你想增加判斷字串方法 , 應該你再增加 標籤/算式 , 再call這標籤就成了
作者: hongrk    时间: 2019-6-5 14:15

本帖最后由 hongrk 于 2019-6-5 14:49 编辑

做了一个通用的版本。
规则:
1.用S2表示本行第2个数,其他同理。
2.本行数的总数用n表示。
3.同一行的小节规则用""包起来,同一大节的规则之间空格隔开。
4.同一规则重复检测格式:"起始位置 间隔 中止位置(直到最后则写n)""其他规则1""其他规则2"
在此格式中,用%%i表示不确定的位置。还可以实现对%%i进行各种运算,用[]包起来即可。
5.可以自创变量进行赋值(不与已用变量冲突即可,如可使用A1、A2、B1等等)。格式相当于省去了set/a的set/a
6.检验部分相当于省去了if的if
举个例子:
"n GTR 3" "3 1 n""S%%i==S[%%i-1]+S[%%i-2]" "S2==50" "1 1 n""B1+=S%%i" "B1 GTR 100"
这是斐波那契数列的规则,且要求第2个数是50,全部数加起来超过100.
这个分析器可以实现之前代码的所有功能,并且要强大出许多。
【BUG这下应该算是彻底修好了!】

代码如下。
  1. @echo off&setlocal enabledelayedexpansion
  2. echo 默认目标文档为“分析器”目录下的2.txt
  3. set/p rule=请拖入规则文档:
  4. rem 先读取规则,分行读取,G系列存规则,变量Gn用于标记这是第几行规则(在下一部分即总共有几行规则)。(G:Gui则)(n:number)
  5. for /f "tokens=*" %%a in (%rule%)do (
  6.   set/a Gn+=1
  7.   for /f "tokens=1*" %%b in ("!Gn! %%a")do set G%%b=%%c
  8. )
  9. set/p shu=请拖入待处理文档:
  10. cls
  11. rem n系列:存每一行的数总数。 S系列(Shu):存每一行的每一个数。 F系列:存是否符合对应规则行,符合为1否则为0.  
  12. rem 按行读取待检测的数,先赋好一行,然后再执行规则,最后判断执行结果。完成后读取下一行数。
  13. (for /f "tokens=*" %%a in (%shu%)do (
  14.   setlocal
  15.   for %%b in (%%a)do set/a n+=1&set S!n!=%%b
  16.   for /l %%b in (1 1 %Gn%)do (
  17.     for %%c in (!G%%b!)do (
  18. rem 把一行规则分解为几节逐一分析检验
  19.       for /f tokens^=1*^ delims^=^" %%d in ("%%~c")do (
  20.         if "%%e"=="" (set forl=&set t=%%d
  21.         )else set t=%%e&for /f "tokens=1-3 delims=,; " %%f in ("%%d")do (
  22.                 set/a Z1=%%f,Z2=%%g,Z3=%%h
  23.                 set "forl=for /l %%i in (!Z1! !Z2! !Z3!^)do"
  24.               )
  25. rem 若此节规则的中间没有引号,说明没有类似"1 1 n"的结构;否则要准备开for /l了。将去除"for /l"结构后的“整节规则”赋给t。
  26.         set "t=!t:""=" "!"
  27. rem 准备开始分割小节规则。
  28.         call :forl %%b
  29.       )
  30. rem 此节规则结束。
  31.     )
  32. rem 此行规则结束。
  33.     set/a f+=f%%b
  34.   )
  35. rem 对此行数,所有规则结束。
  36.   if !f!==0 echo %%a
  37. rem 只要有一行规则完全符合,就不输出
  38.   endlocal
  39. ))>2.txt
  40. exit
  41. rem %t%存整节规则,!t!存小节规则。
  42. :forl
  43. (%forl% (
  44.   for %%j in ("%t%")do (
  45.     set Le=&set Ri=
  46.     set t=%%~j&set t=!t:%%%%i=%%i!
  47. rem 因为前面在整节规则中造出了空格,因此可用for截取小节规则。
  48.     for %%k in ("!t!")do (
  49.       set u=!t:%%~k!
  50.       set center==
  51.       if "!u:~,1!"=="=" set center===
  52.       if "!u:~,1!"=="t" set center=
  53.     )
  54. rem 以上利用字符串替换对"="的检测规律,来分析t,也就是小节规则,是0个/1个/2个等于号中的哪一种。
  55.     for /f "tokens=1-3 delims== " %%k in ("!t!")do (
  56.       set Le.ft=%%k
  57.       if "!center!"=="" (set center=%%l&set Ri.ght=%%m)else set Ri.ght=%%l
  58.     )
  59. rem 分割小节规则
  60.     for %%k in (Le.ft Ri.ght)do (
  61.       set %%k=!%%k:[= !&set %%k=!%%k:]= !
  62.       set QAQ=0
  63.       for %%l in (!%%k!)do (
  64.         2>nul set/a AQA=%%l
  65.         2>nul set/a QAQ+=1,1/(QAQ"&"1^)&&set %%~nk=!%%~nk!%%l||set %%~nk=!%%~nk!!AQA!
  66.       )
  67.     )
  68. rem 处理[]
  69.     if "!center!"=="=" (set/a !Le!=!Ri!)else set/a Le=!Le!,Ri=!Ri!&call :zl %1
  70. rem 若是赋值规则就直接打包set/a;若是比较规则,左右计算后进行比较。
  71.   )
  72. )
  73. )&exit/b
  74. :zl
  75. rem if语句做不到耐心地把感叹号扩充开再判断语句是否合理,所以——
  76. if %Le% %center% %Ri% (if not defined F%1 set F%1=1)else set F%1=0
  77. rem F%1是用来存这行数对应这行规则的判定结果。有一节规则不满足就不算满足此行规则。符合为1,不符合为0.
  78. exit/b
复制代码

作者: Taurus    时间: 2019-6-7 02:40

本帖最后由 Taurus 于 2019-6-7 03:45 编辑

精簡化#24樓代碼 , 以及按8樓要求改為過濾[1~9]、奇偶數、順序數
優化不必要的迴圈至最少
同樣 , 只要把[for %%Z in (2,3,4,5,6,7,8,9) do (] 改為[for %%Z in (2,3,5) do (] 則只過濾2、3、5倍數 , 現在是判斷過濾1-9的
@echo off&setlocal enabledelayedexpansion
del test.txt>nul 2>nul
for /f "tokens=1-5 delims= " %%a in (1.txt) do (
    for  %%f in (%%a %%b %%c %%d %%e) do set/a loop+=1&&set/a var!loop!=-11%%f+10%%f+1%%f
    set/a str=!var5!-!var4!+!var4!-!var3!+!var3!-!var2!+!var2!-!var1!,loop=0
    if "!str!" NEQ "4" call :a %%a %%b %%c %%d %%e
)
test.txt
:a
for %%Z in (2,3,4,5,6,7,8,9) do (
    set/a A=!var1!0/%%Z,B=!var2!0/%%Z,C=!var3!0/%%Z,D=!var4!0/%%Z,E=!var5!0/%%Z
    if "!A:~-1,1!!B:~-1,1!!C:~-1,1!!D:~-1,1!!E:~-1,1!" == "00000" goto :eof
    if "!A:~-1,1!!B:~-1,1!!C:~-1,1!!D:~-1,1!!E:~-1,1!%%Z" == "555552" goto :eof
)
echo %*>>test.txt

註解:
第四行 : 去字串前的[0]的算式 , 原理為 , 把[009090]加上兩個位 ,  -11009090+10009090+1009090=[9090]
算式為-11[string]+-10[string]-1[string]=[Result]

第五行 : 去除[連續數]的算式 , 原理為 , 例如連續數[5,6,7,8,9] , 把9-8+8-7+7-6+6-5=[4] ; 只要是[連續數] , 餘值必然是[4]
算式為E-D+D-C+C-B+B-A=4

第十一行 : 把5組數在結尾補上一個0位 , 再分別除以[1-9] ; 例如[903 , 906 , 909 , 912 , 915] , 除[2]等於[451.5/953.0/454.5/456.0/457.5 ] , 截取小數點後一個位等於[50505] , 小數點後出現餘值等於不能整除 ; 反之 , [903 , 906 , 909 , 912 , 915]除[3] = [301.0/302.0/303.0/304.0/305.0] , 截取小數點後一個位等於[00000] , 小數點後不出現餘值等於能被整除
第十一行通用判斷奇數(被2整除出現00000)、偶數(被2除後出現55555)、1-9倍數(被1-9整除出現00000) , 所以非[00000]也非[55555]之數正是樓主所需篩選出來的值
算式為[A string]/2 , [B string]/2  , [C string]/2 , [D string]/2 , [E string]/2  =   [00000] or [55555] or [0和5的混合字串]

==================================
所以 , 綜合判斷條件其實只是需要[去零]、[去連續數]、[分辨整除數]三條算式




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2