Board logo

标题: [文本处理] 求字符串长度,简短高效的批处理代码(多种算法) [打印本页]

作者: plp626    时间: 2011-4-7 22:38     标题: 求字符串长度,简短高效的批处理代码(多种算法)

这是迄今为至,我多年来看过的批处理代码中,见到的最优美的一段代码,不和大家分享一下实在不好意思。
原以为,求字符串长度的方法在二分法和查表法后不会有突破了,但我发现时我的思想是太懒了。

二分回溯法(现在更正下,准确的叫法应该是优化的二分法)求字符串长度:

原帖:http://www.dostips.com/forum/viewtopic.php?f=3&t=1429
  1. setlocal enabledelayedexpansion
  2. set "$=!%1!#"
  3. set len=&for %%a in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1)do if !$:~%%a^,1!. NEQ . set/a len+=%%a&set $=!$:~%%a!
  4. endlocal&If %2. neq . (set/a%2=%len%)else echo %len%
复制代码
关于求字符串长度,以前论坛里讨论过不少,但就代码长度,支持最长字符串,和执行耗时来综合考虑,
我“个人认为”都没有超越上面这段代码。


把原代码小修小补增加了30多K的字节(原帖是联合256位的表),可以减少相当于大概2~7次set 赋值命令所耗费的时间(效率提高8%~30%):
  1. :strlen <stringVarName> [retvar]
  2. :: 思路: 二分回溯联合查表法
  3. :: 说明: 所求字符串大小范围 0K ~ 8K;
  4. ::    stringVarName ---- 存放字符串的变量名
  5. ::    retvar      ---- 接收字符长度的变量名
  6. setlocal enabledelayedexpansion
  7. set "$=!%1!#"
  8. set N=&for %%a in (4096 2048 1024 512 256 128 64 32 16)do if !$:~%%a!. NEQ . set/aN+=%%a&set $=!$:~%%a!
  9. set $=!$!fedcba9876543210&set/aN+=0x!$:~16,1!
  10. endlocal&If %2. neq . (set/a%2=%N%)else echo %N%
复制代码
对于上面代码
如果所求字符串长度不超过4096:
可以将4096 2048 1024 512 256 128 64 32 16改为2048 1024 512 256 128 64 32 16

如果所求字符串长度不超过2048:
可以将4096 2048 1024 512 256 128 64 32 16改为      1024 512 256 128 64 32 16
以此类推。。。

=============================================================
测试一下效率
  1. @echo off&setlocal enabledelayedexpansion
  2. :: 将strlen函数内敛到变量_strlen中,测试字符串长度小于4096;入口参数#1,返回变量##
  3. set "_strlen=set $=^!#1^!#&set ##=&(for %%a in (2048 1024 512 256 128 64 32 16)do if ^!$:~%%a^!. NEQ . set/a##+=%%a&set $=^!$:~%%a^!)&set $=^!$^!fedcba9876543210&set/a##+=0x^!$:~16,1^!"
  4. :: 生产一个长度为4096字符个数的字符串
  5. set str=.&for /l %%a in (1 1 12)do set str=!str!!str!
  6. :: 测试一下速度,4000次
  7. set bt=%time%
  8. for /l %%a in (1 1 4000)do (
  9.         set #1=!str:~-%%a!
  10.         (%_strlen%)
  11.         echo 长度:!##!
  12. )
  13. set et=%time%
  14. :: 计算花费时间
  15. set /a ct=1!et:~-5,2!!et:~-2!-1!bt:~-5,2!!bt:~-2!,ct+=-6000*("ct>>31")
  16. echo ---------------------&echo 开始时间:%bt%&echo 结束时间:%et%
  17. echo 4000次测试用时:%ct% 跑秒&echo -----------------------
  18. pause
复制代码

作者: plp626    时间: 2011-4-7 23:05

在这里把论坛里求字符串长度的帖子做一个索引,大家可以把这些方法相互做个比较,
也许你能从中提炼出精华得到更代码更简洁效率更高效的方法也不一定。

求字符串长度练习(各种方法,真是大杂烩,很多带有goto循环的和调用三方的方法)

http://www.bathome.net/viewthread.php?tid=1480

当字符串较长时不得不用的方法——二分法
http://bbs.bathome.net/viewthread.php?tid=4219

对字符串长度有限制的查表法:
(9位和40位)http://www.bathome.net/viewthread.php?tid=3136 (6楼)
(16位)http://www.bathome.net/viewthread.php?tid=1249 (15楼)
(255位和1024位)http://www.bathome.net/viewthread.php?tid=5994
关于查表法还有很多相关代码,但思想都来源于9位法,不再列举。
======================================================

下面对这些求字符串长度的典型方法做个大致的汇总(代码均来自上面的索引贴子)
带有goto循环的方法,使得效率极为低下,这里不列举。
调用三方工具求长度的方法(如findstr/o 法,vbs法,for/f +dir法,xcopy法)效率更极为低下,这里不列举

方法一:思路最直接,代码最简短,但效率最低的方法(所求字符串较长时不宜采用)

原帖:http://www.bathome.net/viewthread.php?tid=1480
  1. set/p str=input a string:
  2. set StrMAX=1000
  3. if not defined str set num=0&goto :ok
  4. for /l %%a in (0,1,%StrMAX%) do if "!str:~%%a,1!"=="" set num=%%a&goto :ok
  5. :ok
  6. echo 长度=!num!
复制代码
方法二:适合求长字符串的二分法
原帖:http://bbs.bathome.net/viewthread.php?tid=4219
  1. set /p s=please input a string:
  2. setlocal enabledelayedexpansion
  3. set /a n=8189*2,max=1&set "var="
  4. for /l %%a in (1 1 14) do (
  5.    if defined var set /a n=var
  6.    set /a n/=2
  7.    for %%i in (!n!) do (
  8.       if "!s:~%%i,1!"=="" (set /a var=n) else (
  9.          set s=!s:~%%i!&set /a max+=%%i,var-=%%i
  10. )))  
  11. endlocal&echo 长度:%max%
复制代码
方法2.X 改进的二分搜索法(效率提高不少)
原帖:http://www.dostips.com/forum/viewtopic.php?f=3&t=1429
  1. set /p str=input a string
  2. SETLOCAL ENABLEDELAYEDEXPANSION
  3.     set "str=A!str!"
  4.     set len=0
  5.     for /L %%A in (12,-1,1) do (
  6.         set /a "len|=1<<%%A"
  7.         for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"
  8. ENDLOCAL&echo 长度:%len%
复制代码
方法三:查表法
当所求字符串长度小于16时,速度最快最简短的查表法:
原帖:http://www.bathome.net/viewthread.php?tid=1249 (15楼)
  1. set str=!str!fedcba9876543210&set/a len=0x!str:~15,1!
  2. echo 长度%len%
复制代码
当所求字符串字符数小于256时,速度最快(和上面代码效率相当)但代码较长的查表法
(一般说来,若用较短的程序生产该512表,至少需要16次set赋值语句的执行):
原帖: http://www.bathome.net/viewthread.php?tid=5994
  1. @echo off&setlocal enabledelayedexpansion
  2. set/p str=input a string:
  3. set "$=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff%str%%str%"
  4. set/a len=0x!$:~-512,2!
  5. echo 长度:%len%
  6. pause
复制代码
方法四:等长替换计算法
原帖: 见本贴13楼lllsoslll的代码
(效率低于纯查表法,仅次于二分回溯法,优势在于表的生产不是很占用时间,且代码较短)
注意注意,"SET $=123456789$" 中,等号后的空白字符不是空格符!,而是ascii码为127的那个del字符;
  1. set/p #1=string:?
  2. SET $=123456789$&FOR /L %%a in (1 1 3)Do SET $=!$!!$!!$!!$!!$!!$!
  3. SET $=!#1!`$!$!&SET $=!$:~0,2376!&SET $=!$:*`$=!&SET/A"$=-1,##=2372-(!$:123456789$=11+!+!$:~-1!)"
  4. echo length=!##!
复制代码
其他方法:待续。。。

--------------------------------- 更新1 -------------------------------
下面算法思想是基于16查表法,先求出待测字符串长度对16的"倍数值",再求对16的余数值;最后相加
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. :: 要测试的字符串
  4. set $1=123456789012345678901234567890123456789012345670
  5. :: 该字符串长度不超过256且大于0
  6. set $2=256
  7. rem ----------------------------------------------
  8. rem ----------------------------------------------
  9. echo 长度为 %$%
  10. pause
复制代码
当$2指定为256,这段代码的耗时相当于10次set赋值操作的耗时,
对于短字符串求长度,效率和代码体积上,很实用(效率很高,且算法简单,容易理解记忆)
---------------------------------------------------------------------

如果把16位表换为256为表, 那么对于小于4096长度以内的字符串,由于512位的表占用了不少空间, 会影响 外部环境 赋值,取值操作效率,
关于这个问题, 有时间我再做测试,

预期这个效率兴许会比1楼代码效率高。。。
经测试, 对于长字符串,该方法较比1楼的代码 效率提高了25%左右
作者: 随风    时间: 2011-4-7 23:48

本帖最后由 随风 于 2011-4-7 23:54 编辑

非常巧妙的方法,赞!
集效率简短于一身
果然~~
作者: caruko    时间: 2011-4-8 16:27

也是二分法的一种..
每次检测后就截断的确可以省去IF判断,很巧妙!
至于直接使用4096省去计算,早已经有用过。
而16位以后改查表法感觉提升的效率有限。

那个移位法,没怎么看懂,但是也是计算2的N次方,的确不如直接用4096快。
作者: CrLf    时间: 2011-4-8 17:18

也想过类似的思路,但是当时思维惯性,只想到了二分回溯补位,并没有用变量偏移,一墙之隔啊,可惜当时没想这么深入,呵呵。
作者: plp626    时间: 2011-4-8 22:40

有一种直觉,几乎接近真实了
就求字符串长度来说,还有比一楼更快代码更简洁的代码。
作者: CrLf    时间: 2011-4-9 09:25

本帖最后由 zm900612 于 2011-4-9 09:26 编辑

我的想法:
  1. @echo off
  2. set "$=%1"
  3. setlocal enabledelayedexpansion
  4. set len=8192
  5. (for %%a in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1)do (
  6. set /a len-="%%a!$:~%%a,1!"||set $=!$:~%%a!
  7. ))2>nul
  8. echo %len%
  9. ::未考虑字符串包含数字、特殊字符的情况
复制代码
稍加改进后仍然难以克服特殊字符的难关:
  1. @echo off
  2. set "$=%1"
  3. setlocal enabledelayedexpansion
  4. set len=8192
  5. (for %%a in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1)do (
  6. set /a len-="%%a*^!(1-1!$:~%%a,1!)"||set $=!$:~%%a!
  7. ))2>nul
  8. echo %len%
  9. pause
  10. ::不惧怕数字了,但是仍然没有办法在set /a中很好地转义特殊字符,看来要想通用,那个if是不能省的了
复制代码

作者: terse    时间: 2011-4-10 11:52

当多数人的思维在二分法和查表法后 正如plp626兄说道 "我们的思想是太懒了"
看这段精妙代码后 和plp626兄一样 我“个人认为” 似乎都没有超越上面这段代码
现在想法 结合查表法至 2048 位 然后 for %%a in (4096 2048)do...
表太长了  不贴这里了
作者: netbenton    时间: 2011-12-21 09:44

本帖最后由 netbenton 于 2011-12-21 09:45 编辑

发现,楼主的这个代码和16字符限制的查表法合并才是最佳的,即8 4 2 1项用查表法代替。效率应该可以提高20%,增加的字符也不多
作者: plp626    时间: 2012-3-29 10:46

同findstr类似,又一个外部命令求字符串长度的方法(适合于纯英文字符),连续的宽字符被视为1个字符;
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set str=www.bathome.net
  4. set n=0
  5. for /f "delims=" %%a in ('cmd/u/cecho !str!^|more')do set/a n+=1
  6. set n
  7. pause
复制代码
如果要给英文字符串中每个字符后加换行符,这是个简洁的方案;
作者: wankoilz    时间: 2014-8-5 01:45

本帖最后由 wankoilz 于 2014-8-5 02:00 编辑

无聊翻看经典帖子,发现前两段代码好像都少算了一个字符,比如第二段代码,在执行到
  1. set $=!$!fedcba9876543210&set/aN+=0x!$:~16,1!
复制代码
的时候,变量$的长度范围应该是1-16(不考虑$长度为0),而fedcba9876543210只能表达0-15
所以似乎应该把这一句改成这样:
  1. set $=!$!!$!100f0e0d0c0b0a090807060504030201&set/aN+=0x!$:~32,2!
复制代码
小小疏忽,请明察
作者: xxpinqz    时间: 2014-8-5 11:41

回复 11# wankoilz

因为源代码在字符串后补了一个字符,所以才用位移16,例字符串"abcd",实际扩展开来:$=abcd#fedcba9876543210    所以len=4

fedcba9876543210,这个本来就是取15位以内长度,没人说能取16位。
作者: wankoilz    时间: 2014-8-5 12:34

本帖最后由 wankoilz 于 2014-8-5 12:38 编辑

哦哦对的,是我自己没仔细看,在原字符串后加上一位就对了。
楼主的代码确实是简练!
不过对于我来说,不改动原字符串更容易理解 :
  1. :strlen <stringVarName> [retvar]
  2. :: 思路: 二分回溯联合查表法
  3. :: 说明: 所求字符串大小范围 0K ~ 8K;
  4. ::    stringVarName ---- 存放字符串的变量名
  5. ::    retvar      ---- 接收字符长度的变量名
  6. setlocal enabledelayedexpansion
  7. set "$=!%1!"
  8. set N=&for %%a in (4096 2048 1024 512 256 128 64 32 16)do if !$:~%%a!. NEQ . set/aN+=%%a&set $=!$:~%%a!
  9. set $=!$!!$!100f0e0d0c0b0a090807060504030201
  10. set/aN+=0x!$:~32,2!&set/aN+=0x!$:~16,1!
  11. endlocal&If %2. neq . (set/a%2=%N%)else echo %N%
复制代码

作者: CrLf    时间: 2014-8-5 16:33

本帖最后由 CrLf 于 2014-8-5 23:15 编辑

回复 13# wankoilz


    看来个人有个人的习惯写法,我比较倾向用其他手段代替补位,这样可以兼容最长的变量(除了 , 这个变态的变量名),不过代码就稍显冗长了:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /l %%a in (1 1 8189) do set s=!s!;
  3. call :strlen s len
  4. echo len=%len%
  5. pause&exit/b
  6. :strlen <stringVarName> [retvar]
  7. :: 思路: 二分回溯联合查表法
  8. :: 说明: 所求字符串大小范围 0K ~ 8K;
  9. ::    stringVarName ---- 存放字符串的变量名
  10. ::    retvar      ---- 接收字符长度的变量名
  11. setlocal enabledelayedexpansion&set $=!%1!&set N=0
  12. if defined $ (
  13. for %%a in (4095 2047 1023 511 255 127 63 31 15)do if !$:~%%a!. NEQ . set/aN-=~%%a&set $=!$:~%%a,-1!
  14. set $=!$!fedcba987654321&set/aN+=0x!$:~15,1!
  15. )
  16. endlocal&If %2. neq . (set %2=%N%)else echo %N%
复制代码

作者: wankoilz    时间: 2014-8-5 20:58     标题: 标题

本帖最后由 wankoilz 于 2014-8-5 21:01 编辑

这样的话,fedcba9876543210中的0都可以省了。
不过我还是觉得用4096  2048……更好,因为每个数字正好对应于二进制上的一位,理解和计算都更好一点。
作者: xxpinqz    时间: 2014-8-5 23:02

0是用来防空的。。。。
作者: CrLf    时间: 2014-8-5 23:15

回复 16# xxpinqz


    他应该是回复14楼的...
作者: wankoilz    时间: 2014-8-6 01:06

对的,不好意思,手机太老了
作者: wangx    时间: 2014-11-3 16:42

太棒了,非常受用,收藏了。
作者: 踏沙行    时间: 2018-8-1 09:15

回复 1# plp626

楼主的算法确实精简高效,把数学计算用到了极致。但这两天在学习时发现,该代码存在以下问题:
1、使用for /l (128 64 32...)时,判断某数为空后折半,需要把括号中的数减一后再判断,就如
if "!a:~127,1!" neq ""  set /a "len+=%%a",而不是if "!a:~%%a,1!" neq ""  set /a "len+=%%a"。用这种算法,固然可以在全部计算后最终加1得到正确长度,但是毕竟原代码结果不正确。

2、第9句的set/a "len+=0x!s:~16,1!",应该是set/a "len+=0x!s:~15,1!"

说的不对的地方,请斧正。

我的代码如下:
  1. @echo off
  2. set "var=1234567890abcdefghijklmnopqrstuv12345678901234567890abcdefghijklmnopqrstuv12345678901234567890abcdefghijklmnopqrstuv12345678901"
  3. call :Len var,n
  4. echo 长度为%n%
  5. pause&exit
  6. :Len
  7. Setlocal enabledelayedexpansion
  8. set "s=!%1!"
  9. for %%a in (512 256 128 64 32 16) do (
  10. set/a "m1=%%a-1" &call set "b1=%%s:~!m1!,1%%"
  11. if "!b1!" neq "" (
  12. set/a "len+=%%a" &set "s=!s:~%%a!"
  13. if "!s!"=="" goto ok )
  14. )
  15. set "s=!s!fedcba9876543210" &set/a "len+=0x!s:~15,1!"
  16. :ok
  17. endlocal&set/a "%2=%len%"&goto:eof
  18. pause
复制代码

作者: zaqmlp    时间: 2018-8-1 09:32

回复 20# 踏沙行

set "$=!%1!#"
这不是没有意义的
作者: Batcher    时间: 2018-8-1 10:27

回复 20# 踏沙行


    能否举例说明一下原代码哪个结果不正确?
作者: 踏沙行    时间: 2018-8-1 14:59

回复 22# Batcher
  1. @echo off
  2. set a="1234567890abcdef"
  3. call :Len a n
  4. echo 长度为%n%
  5. pause&exit
  6. :Len
  7. setlocal enabledelayedexpansion
  8. set "$=!%1!#"
  9. set len=&for %%a in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1)do if !$:~%%a^,1!. NEQ . set/a len+=%%a&set $=!$:~%%a!
  10. endlocal&If %2. neq . (set/a%2=%len%)else echo %len%
复制代码
执行结果:长度为18
实际上应该是16
作者: Batcher    时间: 2018-8-1 15:09

回复 23# 踏沙行


楼主代码没问题,是你的理解不太准确。

set a="1234567890abcdef"
这种写法,set命令会认为变量a的值是包含双引号的,18位是正确的

set "a=1234567890abcdef"
这种写法,set命令会认为变量a的值是不包含双引号的,16位是正确的
作者: 踏沙行    时间: 2018-8-1 15:18

本帖最后由 踏沙行 于 2018-8-1 15:40 编辑

回复 24# Batcher
谢谢,是我写的有问题。
修正后再测试,代码如下:
  1. @echo off
  2. set "a=1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
  3. rem a的长度为64
  4. call :Ten a n
  5. echo 长度为%n%
  6. pause&exit
  7. :Ten
  8. setlocal enabledelayedexpansion
  9. set "$=!%1!#"
  10. set "len="
  11. for %%a in (64 32 16 8 4 2 1) do (
  12. if !$:~%%a^,1!. NEQ . set/a len+=%%a&set $=!$:~%%a!
  13. set/a "T=T+1"&echo.第!T!次判断
  14. )
  15. endlocal&If %2. neq . (set/a%2=%len%)else echo %len%
复制代码
运行结果为:
第1次判断
第2次判断
第3次判断
第4次判断
第5次判断
第6次判断
第7次判断
长度为64
请按任意键继续. . .

【问题】本来字符长度为64,可以一次判断出结果。但是因为使用了set "$=!%1!#",让计算次数增加了6次
而且,对于if !$:~%%a^,1!. NEQ .这样的判断,如果字符串中存在有.(点号),也会影响正常判断吧
作者: Batcher    时间: 2018-8-1 15:44

回复 25# 踏沙行


让计算次数增加了6次

你有更加优化的代码吗?发出来大家一起讨论一下吧
如果字符串中存在有.(点号),也会影响正常判断吧

把你的测试用例和测试结果发出来看看
作者: 踏沙行    时间: 2018-8-1 15:59

回复 26# Batcher
  1. @echo off
  2. set "a=1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
  3. call :Ten a n
  4. echo 长度为%n%
  5. pause&exit
  6. :Ten
  7. setlocal enabledelayedexpansion
  8. set "$=!%1!#"
  9. set "len="&for %%a in (4096 2048 1024 256 128 64 32 16 8 4 2 1) do (if "!$:~%%a,1!" NEQ "" set/a len+=%%a&set "$=!$:~%%a!" &if "!$:~1!"=="" goto ok)
  10. set "s=!s!fedcba9876543210" &set/a "len+=0x!s:~16,1!"
  11. :ok
  12. endlocal&set/a "%2=%len%"&goto:eof
  13. pause
复制代码
增加 if "!$:~1!"=="" goto ok,可以在刚好够2分时,及时跳出循环。
作者: nwm310    时间: 2018-8-5 11:17

查表法
  1. ::0 ~ 255字
  2. setlocal enableDelayedExpansion
  3. set "s=your string"
  4. set a=□0□1□2□3□4□5□6□7□8□9□A□B□C□D□E□F
  5. set "$=!%a:□=!!a:□=%!!s!!s!"
  6. set /a len=0x!$:~-512,2!
  7. echo %len%
复制代码
  1. :: 0 ~ 1279字   (8191 /6 = 1365)
  2. setlocal enableDelayedExpansion
  3. set "s=your string"
  4. set a=□0□1□2□3□4□5□6□7□8□9□A□B□C□D□E□F
  5. set d=!%a:□=!!a:□=□%!
  6. set b=□0□1□2□3□4
  7. set "$=!%b:□=!!d:□=%!!s!!s!!s!"
  8. :: (0x4FF + 1 ) *3 = 1280 * 3 = 3840
  9. set /a len=0x!$:~-3840,3!
  10. echo %len%
复制代码

作者: CrLf    时间: 2018-8-5 20:45

本帖最后由 CrLf 于 2018-8-5 21:02 编辑

回复 28# nwm310


    挺好的思路
    把变量拆分成7份分别查询,就可以查8191字符长度内的所有变量了
作者: cfwyy77_bat    时间: 2018-8-7 09:05

精典老贴! 再学习学习。
作者: 523066680    时间: 2018-12-19 11:32

回复 29# CrLf

这两天偶然才翻到,感觉这句操作真的骚
  1. !%a:□=!!a:□=%!
复制代码
老了,思路跟不上了~
作者: SQYSQYSQY    时间: 2019-1-1 11:50

本帖最后由 SQYSQYSQY 于 2019-1-1 11:57 编辑
  1. :ac
  2. set ac=!%~1!!%~1!!%~1!^
  3. 3FF3FE3FD3FC3FB3FA3F93F83F73F63F53F43F33F23F13F03EF3EE3ED3EC3EB3EA3E93E83E73E63E53E43E33E23E13E03DF3DE3DD3DC3DB3DA3D93D83D73D63D53D43D33D23D13D03CF3CE3CD3CC3CB3CA3C93C83C73C63C53C43C33C23C13C03BF3BE3BD3BC3BB3BA3B93B83B73B63B53B43B33B23B13B03AF3AE3AD3AC3AB3AA3A93A83A73A63A53A43A33A23A13A039F39E39D39C39B39A39939839739639539439339239139038F38E38D38C38B38A38938838738638538438338238138037F37E37D37C37B37A37937837737637537437337237137036F36E36D36C36B36A36936836736636536436336236136035F35E35D35C35B35A35935835735635535435335235135034F34E34D34C34B34A34934834734634534434334234134033F33E33D33C33B33A33933833733633533433333233133032F32E32D32C32B32A32932832732632532432332232132031F31E31D31C31B31A31931831731631531431331231131030F30E30D30C30B30A3093083073063053043033023013002FF2FE2FD2FC2FB2FA2F92F82F72F62F52F42F32F22F12F02EF2EE2ED2EC2EB2EA2E92E82E72E62E52E42E32E22E12E02DF2DE2DD2DC2DB2DA2D92D82D72D62D52D42D32D22D12D02CF2CE2CD2CC2CB2CA2C92C82C72C62C52C42C32C22C12C02BF2BE2BD2BC2BB2BA2B92B82B72B62B52B42B32B22B12B02AF2AE2AD2AC^
  4. 2AB2AA2A92A82A72A62A52A42A32A22A12A029F29E29D29C29B29A29929829729629529429329229129028F28E28D28C28B28A28928828728628528428328228128027F27E27D27C27B27A27927827727627527427327227127026F26E26D26C26B26A26926826726626526426326226126025F25E25D25C25B25A25925825725625525425325225125024F24E24D24C24B24A24924824724624524424324224124023F23E23D23C23B23A23923823723623523423323223123022F22E22D22C22B22A22922822722622522422322222122021F21E21D21C21B21A21921821721621521421321221121020F20E20D20C20B20A2092082072062052042032022012001FF1FE1FD1FC1FB1FA1F91F81F71F61F51F41F31F21F11F01EF1EE1ED1EC1EB1EA1E91E81E71E61E51E41E31E21E11E01DF1DE1DD1DC1DB1DA1D91D81D71D61D51D41D31D21D11D01CF1CE1CD1CC1CB1CA1C91C81C71C61C51C41C31C21C11C01BF1BE1BD1BC1BB1BA1B91B81B71B61B51B41B31B21B11B01AF1AE1AD1AC1AB1AA1A91A81A71A61A51A41A31A21A11A019F19E19D19C19B19A19919819719619519419319219119018F18E18D18C18B18A18918818718618518418318218118017F17E17D17C17B17A17917817717617517417317217117016F16E16D16C16B16A16916816716616516416316216116015F15E15D15C15B15A159158^
  5. 15715615515415315215115014F14E14D14C14B14A14914814714614514414314214114013F13E13D13C13B13A13913813713613513413313213113012F12E12D12C12B12A12912812712612512412312212112011F11E11D11C11B11A11911811711611511411311211111010F10E10D10C10B10A1091081071061051041031021011000FF0FE0FD0FC0FB0FA0F90F80F70F60F50F40F30F20F10F00EF0EE0ED0EC0EB0EA0E90E80E70E60E50E40E30E20E10E00DF0DE0DD0DC0DB0DA0D90D80D70D60D50D40D30D20D10D00CF0CE0CD0CC0CB0CA0C90C80C70C60C50C40C30C20C10C00BF0BE0BD0BC0BB0BA0B90B80B70B60B50B40B30B20B10B00AF0AE0AD0AC0AB0AA0A90A80A70A60A50A40A30A20A10A009F09E09D09C09B09A09909809709609509409309209109008F08E08D08C08B08A08908808708608508408308208108007F07E07D07C07B07A07907807707607507407307207107006F06E06D06C06B06A06906806706606506406306206106005F05E05D05C05B05A05905805705605505405305205105004F04E04D04C04B04A04904804704604504404304204104003F03E03D03C03B03A03903803703603503403303203103002F02E02D02C02B02A02902802702602502402302202102001F01E01D01C01B01A01901801701601501401301201101000F00E00D00C00B00A009008007006005004^
  6. 003002001000&set /a "%2=0x!ac:~3069,3!"&goto :eof
复制代码
代码长点,但只要变量长度不超过1024,都可以用下面方法计算,保证高效

只要
call :ac 变量名 a
%a%就是长度
(注:变量名不带引号,不带百分号)


原理很简单,受楼主启发,将其变个型。
有人问这么一长串咋得到,用for命令即可。
@echo off
set "a="
for %%a in (3 2 1 0) do (
for %%b in (F E D C B A 9 8 7 6 5 4 3 2 1 0) do (
for %%c in (F E D C B A 9 8 7 6 5 4 3 2 1 0) do (
call set a=%%a%%%%a%%b%%c
)
)
)
echo %a%>1.txt
作者: cc5511    时间: 2020-8-29 00:39

太专业了 厉害啊




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