本帖最后由 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这下应该算是彻底修好了!】
代码如下。- @echo off&setlocal enabledelayedexpansion
-
- echo 默认目标文档为“分析器”目录下的2.txt
- set/p rule=请拖入规则文档:
- rem 先读取规则,分行读取,G系列存规则,变量Gn用于标记这是第几行规则(在下一部分即总共有几行规则)。(G:Gui则)(n:number)
- for /f "tokens=*" %%a in (%rule%)do (
- set/a Gn+=1
- for /f "tokens=1*" %%b in ("!Gn! %%a")do set G%%b=%%c
- )
-
- set/p shu=请拖入待处理文档:
- cls
- rem n系列:存每一行的数总数。 S系列(Shu):存每一行的每一个数。 F系列:存是否符合对应规则行,符合为1否则为0.
- rem 按行读取待检测的数,先赋好一行,然后再执行规则,最后判断执行结果。完成后读取下一行数。
- (for /f "tokens=*" %%a in (%shu%)do (
- setlocal
- for %%b in (%%a)do set/a n+=1&set S!n!=%%b
- for /l %%b in (1 1 %Gn%)do (
- for %%c in (!G%%b!)do (
- rem 把一行规则分解为几节逐一分析检验
- for /f tokens^=1*^ delims^=^" %%d in ("%%~c")do (
- if "%%e"=="" (set forl=&set t=%%d
- )else set t=%%e&for /f "tokens=1-3 delims=,; " %%f in ("%%d")do (
- set/a Z1=%%f,Z2=%%g,Z3=%%h
- set "forl=for /l %%i in (!Z1! !Z2! !Z3!^)do"
- )
- rem 若此节规则的中间没有引号,说明没有类似"1 1 n"的结构;否则要准备开for /l了。将去除"for /l"结构后的“整节规则”赋给t。
- set "t=!t:""=" "!"
- rem 准备开始分割小节规则。
- call :forl %%b
- )
- rem 此节规则结束。
- )
- rem 此行规则结束。
- set/a f+=f%%b
- )
- rem 对此行数,所有规则结束。
- if !f!==0 echo %%a
- rem 只要有一行规则完全符合,就不输出
- endlocal
- ))>2.txt
- exit
-
- rem %t%存整节规则,!t!存小节规则。
- :forl
- (%forl% (
- for %%j in ("%t%")do (
- set Le=&set Ri=
- set t=%%~j&set t=!t:%%%%i=%%i!
- rem 因为前面在整节规则中造出了空格,因此可用for截取小节规则。
- for %%k in ("!t!")do (
- set u=!t:%%~k!
- set center==
- if "!u:~,1!"=="=" set center===
- if "!u:~,1!"=="t" set center=
- )
- rem 以上利用字符串替换对"="的检测规律,来分析t,也就是小节规则,是0个/1个/2个等于号中的哪一种。
- for /f "tokens=1-3 delims== " %%k in ("!t!")do (
- set Le.ft=%%k
- if "!center!"=="" (set center=%%l&set Ri.ght=%%m)else set Ri.ght=%%l
- )
- rem 分割小节规则
- for %%k in (Le.ft Ri.ght)do (
- set %%k=!%%k:[= !&set %%k=!%%k:]= !
- set QAQ=0
- for %%l in (!%%k!)do (
- 2>nul set/a AQA=%%l
- 2>nul set/a QAQ+=1,1/(QAQ"&"1^)&&set %%~nk=!%%~nk!%%l||set %%~nk=!%%~nk!!AQA!
- )
- )
- rem 处理[]
- if "!center!"=="=" (set/a !Le!=!Ri!)else set/a Le=!Le!,Ri=!Ri!&call :zl %1
- rem 若是赋值规则就直接打包set/a;若是比较规则,左右计算后进行比较。
- )
- )
- )&exit/b
-
- :zl
- rem if语句做不到耐心地把感叹号扩充开再判断语句是否合理,所以——
- if %Le% %center% %Ri% (if not defined F%1 set F%1=1)else set F%1=0
- rem F%1是用来存这行数对应这行规则的判定结果。有一节规则不满足就不算满足此行规则。符合为1,不符合为0.
- exit/b
复制代码
|