[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
回复 35# terse


显然,这说明预处理耗时随代码长度的增长不是线性增长的,看来代码简短是保证效率高的一个要求。。。

TOP

为什么 测试值这么高啊 比用FC搞个临时文件也高好多
  1. :::::::::::::::::::::::::::::::: !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
  2. @echo off
  3. set /p var=<%0
  4. setlocal EnableDelayedExpansion
  5. for /l %%i in (32 1 126) do (
  6.    if defined _"!var:~%%i,1!" (
  7.       set "#!var:~%%i,1!=!var:~%%i,1!"
  8.       set "$#!var:~%%i,1!=%%i"
  9.    ) else set _"!var:~%%i,1!"=!var:~%%i,1!&set "$!var:~%%i,1!=%%i"
  10. )
  11. set str= ^^!"$%%&'()*+,-./09:;<=>?@AZ[^^_`az|}~
  12. set "Slen=!str!"
  13. for %%i in (4096 2048 1024 512 256 128 64 32 16)do if "!Slen:~%%i!" NEQ "" set/aLen+=%%i&set Slen=!Slen:~%%i!
  14. set Slen=!Slen!FEDCBA9876543210&set/aLen+=0x!Slen:~16,1!
  15. ECHO !LEN!
  16. for /l %%i in (0 1 !Len!) do (
  17.     for /f "delims=" %%j in ("!str:~%%i,1!") do (
  18.         if "%%j" == "" (set ANS=!ANS! 33)else (
  19.            if "!#%%j!" equ "" (if "!$%%j!" equ "" (set ANS=!ANS! 61)else set ANS=!ANS! !$%%j!) else (
  20.               if "!#%%j!" lss "%%j" (set ANS=!ANS! !$%%j!) else set ANS=!ANS! !$#%%j!
  21.            )
  22.         )
  23.     )
  24. )
  25. echo!ANS!
  26. pause
复制代码

TOP

本帖最后由 plp626 于 2012-3-5 10:42 编辑

回复 30# plp626

:: char2asc 版本2(二分法)每次调用相当于执行20次左右set赋值

    接30楼:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. :: 初始化: 定义单字符if顺序表@ifasc; 全局变量 @ifcode
  4. call ascmap.cmd /437 @
  5. set @ifcode=20FF090A0B0C0D2101020304050607080E0F101112131415161718191A1B1C1D1E1F7F272D222324252628292A2C2E2F3A3B3F405B5C5D5E5F607B7C7D7EADA82BF93C3D3EF1AEAFF6FBEFF7F0F3F2A9F4F5FEC4CDB3BADAD5D6C9BFB8B7BBC0D4D3C8D9BEBDBCC3C6C7CCB4B5B6B9C2D1D2CBC1CFD0CAC5D8D7CEDFDCDDDEDBB0B1B29B9C9DAAF8E6FA9E30ACAB3132FD33343536373839EC6141A6A08583848E868F91926242634387806444654582908A888966469F674768486949A18D8C8B6A4A6B4B6C4C6D4D6EFC4EA4A56F4FA7A2959394997050715172527353E174547555A39796819A7656775778587959987A5AE0E2EBEEE9E3E5E4E7EDE8EA
  6. for /l %%a in (0 2 510)do for %%b in ("!@ifcode:~%%a,2!")do set @ifasc=!@ifasc!!@:~0x%%~b,1!
  7. ::char2asc版本2(code by plp) 入口参数#1,出口参数##,需要全局变量@ifasc和@ifcode
  8. set #1=A
  9. set $=!@ifasc!
  10. set n=0&for %%a in (128 64 32 16 8 4 2 1)do if "!#1!" geq "!$:~%%a,1!" set $=!$:~%%a!&set/a n+=%%a*2
  11. set/a ##=0x!@ifcode:~%n%,2!
  12. set ##
  13. pause
复制代码
经比较,28楼char2asc(耗时比2100+),效率略胜二分法版本(耗时比2400+)
1

评分人数

    • CrLf: 应该是最快的办法了吧技术 + 1

TOP

我的三个方案都很老实,没有什么出彩的地方(而且还内置了你的函数),但还是贴出来吧...

com 方案:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set str= ^^!"$%%&'()*+,-./09:;<=>?@AZ[^_`az|}~
  4. set<nul>$ /p=@!str!
  5. debug asc.com<%0 >nul 2>nul
  6. asc<$>ans.txt
  7. for /f "delims=" %%a in (ans.txt) do set ans=%%a
  8. echo %ans%
  9. pause&exit
  10. e100 B4 08 CD 21 B4 00 BB 64 00 E8 23 00 B3 0A 89 C8
  11. e110 E8 1C 00 88 CA 80 C2 30 CD 21 B2 20 CD 21 B4 0B
  12. e120 CD 21 3C 00 75 DA B4 09 BA 43 01 CD 21 CD 20 F6
  13. e130 F3 88 E1 38 F8 74 0B B7 FF B4 02 88 C2 80 C2 30
  14. e140 CD 21 C3 0D 0A 24
  15. rcx
  16. 46
  17. w
  18. q
复制代码
fc 方案
  1. @echo off
  2. set str=0123_ABCDXYZabcdxyz
  3. setlocal enabledelayedexpansion
  4. set<nul>$ /p"=@!str!"
  5. fc /b $ %comspec%>#
  6. for /f "eol=F skip=2 tokens=2" %%a in (#) do set "ans=!ans!%%a "
  7. echo %ans%
  8. pause
复制代码
纯内部命令方案(0x20~0x7f 范围):
  1. @echo off&setlocal enabledelayedexpansion
  2. set str= ^^!"$%%&'()*+,-./09:;<=>?@AZ[^_`az|}~
  3. set $=!str!#
  4. set N=&for %%z in (4096 2048 1024 512 256 128 64 32 16)do if !$:~%%z!. NEQ . set/aN+=%%z&set $=!$:~%%z!
  5. set $=!$!fedcba9876543210&set/aN+=0x!$:~16,1!-1
  6. set $= ^^!"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^_`abcdefghijklmnopqrstuvwxyz{|}~
  7. set "$=                                !$!"
  8. (for /l %%a in (32 1 127) do (
  9.    for /f "delims=" %%b in (":!$:~%%a,1!") do if "!str%%b=!" neq "!str!" echo %%a !$:~%%a,1!
  10. ))>#
  11. set $=
  12. for /l %%a in (0 1 %n%) do (
  13.    for /f "tokens=1,2 delims= " %%b in (#) do (
  14.       if "!str:~%%a,1!"=="%%c" set "ans=!ans!%%b "
  15.    )
  16. )
  17. echo %ans%
  18. pause
复制代码
纯内部命令方案([a-z_A-Z] 范围),结果测试时反而没有前一个方案快:
  1. @echo off
  2. set str=0123_ABCDXYZabcdxyz
  3. setlocal enabledelayedexpansion
  4. set $=!str!
  5. set N=&for %%z in (4096 2048 1024 512 256 128 64 32 16)do if !$:~%%z!. NEQ . set/aN+=%%z&set $=!$:~%%z!
  6. set $=!$!fedcba9876543210&set/aN+=0x!$:~16,1!
  7. set $=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz
  8. (for %%z in ("48 1 57" "65 1 90" "96 1 122") do (
  9.    for /l %%a in (%%~z) do (
  10.       for /f "delims=" %%b in ("!$:~,1!") do (
  11.          if "!str%%b=!" neq "!str!" echo %%a !$:~,1!
  12.          set $=!$:~1!
  13.       )
  14.    )
  15. ))>#
  16. set $=
  17. for /l %%a in (0 1 !n!) do (
  18.    for /f "tokens=1,2 delims= " %%b in (#) do (
  19.       if "!str:~%%a,1!"=="%%c" set "$=!$!%%b "
  20.    )
  21. )
  22. set ans=!$:96=95!
  23. echo %ans%
  24. pause
复制代码
1

评分人数

    • plp626: 辛苦了,PB + 10 技术 + 1

TOP

回复 29# plp626


    貌似是我电脑上的内部命令运行太慢...@echo off 效率为 20312.8HZ
"find/?"与"@echo off" 耗时比=1657
"find/?"与"set a=#4647" 耗时比=1281

另:判断是否大/小写时我更喜欢用 delims
  1. set chr=a
  2. for /f "delims=ABCDEFGHIJKLMNOPQRSTUVWXYZ" %%a in ("%chr%") do echo 小写
复制代码

TOP

将ascii输出到文件,然后调用debug来显示行不?

TOP

本帖最后由 plp626 于 2012-3-3 10:41 编辑

费力不讨好,楼上上的代码#char2asc耗时不过是下面代码1/6~1/10,而消耗的空间代价可读性代价是惨重的;
  1. call ascmap.cmd @
  2. set #1=A
  3. for /l %%a in (0 1 127)do if /i "!@:~%%a,1!"=="!#1!" set ##=%%a
  4. set ##
复制代码
--------------------------------------

不过又想到一个二分法,把ascii表中的字符按if比较顺序排列,任意字符二分法7次可定位索引值,这和求字符串长度一样了;
  1. 带引号单字符
  2. 20 FF 09 0A 0B 0C 0D 21 01 02 03 04 05 06 07 08 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 7F 27 2D 22 23 24 25 26 28 29 2A 2C 2E 2F 3A 3B 3F 40 5B 5C 5D 5E 5F 60 7B 7C 7D 7E AD A8 2B F9 3C 3D 3E F1 AE AF F6 FB EF F7 F0 F3 F2 A9 F4 F5 FE C4 CD B3 BA DA D5 D6 C9 BF B8 B7 BB C0 D4 D3 C8 D9 BE BD BC C3 C6 C7 CC B4 B5 B6 B9 C2 D1 D2 CB C1 CF D0 CA C5 D8 D7 CE DF DC DD DE DB B0 B1 B2 9B 9C 9D AA F8 E6 FA 9E 30 AC AB 31 32 FD 33 34 35 36 37 38 39 EC 61 41 A6 A0 85 83 84 8E 86 8F 91 92 62 42 63 43 87 80 64 44 65 45 82 90 8A 88 89 66 46 9F 67 47 68 48 69 49 A1 8D 8C 8B 6A 4A 6B 4B 6C 4C 6D 4D 6E FC 4E A4 A5 6F 4F A7 A2 95 93 94 99 70 50 71 51 72 52 73 53 E1 74 54 75 55 A3 97 96 81 9A 76 56 77 57 78 58 79 59 98 7A 5A E0 E2 EB EE E9 E3 E5 E4 E7 ED E8 EA
复制代码

TOP

本帖最后由 plp626 于 2012-3-3 09:20 编辑
版本二:
一次任务与一次“@echo off命令”耗时比=1571
一次任务与一次“@echo off命令”耗时比=1463
用 ...
CrLf 发表于 2012-3-2 05:16



    你这个调用外部命令,效率还这么高?

我的测试了下,版本二目前耗时比2100+

你机子 调用一次"find/?"与执行一次"@echo off" 的耗时比?

我的环境 "find/?"与"@echo off" 耗时比=4281;
          "find/?"与"set a=#4647" 耗时比=2437;


我的机子环境:
  1. d:\Documents_and_Settings\plp2\desktop>cd.>f.t&cd.>g.t
  2. d:\Documents_and_Settings\plp2\desktop>cff.cmd "@echo off" "set a=1" "set a=^!random:~2,1^!"; "set a=^!random:2=#^!"; "set abcd12345678901234567890=$$"; "call set a=1234567890"; "call set/a a=2" "call set f=%%a%%"; popd "setlocal&endlocal"; "if a==0 ?"; "for %a in (1)do set b=%a"; "for /f %a in ("1")do set b=%a"; "ver>nul"; "echo off>a.t" "echo.>b.t 4>a.t" "echo.>b.t" "if exist xxxx.txt ?"; "for %a in (#.txt)do set x=%a"; rem; "copy/b f.t+g.t f.t>nul"; "copy f.t+g.t f.t>nul" shift "fc/? >nul" "findstr/? >nul" "find/? >nul"
  3. Microsoft Windows XP [版本 5.1.2600]
  4. Genuine Intel(R) CPU           T1600  @ 1.66GHz
  5. NUMBER_OF_PROCESSORS=2
  6. ------------ CMD指令测试 -------------
  7. "@echo off"                           @ 119870.7 Hz
  8. "set a=1"                             @  79261.2 Hz
  9. "set a=6"                             @  76784.3 Hz
  10. "set a=#4647"                         @  68252.7 Hz
  11. "set abcd12345678901234567890=$$"     @  58490.4 Hz
  12. "call set a=1234567890"               @    534.2 Hz
  13. "call set/a a=2"                      @   5670.3 Hz
  14. "call set f=%%a%%"                    @    566.6 Hz
  15. "popd"                                @ 106830.4 Hz
  16. "setlocal&endlocal"                   @   2934.6 Hz
  17. "if a==0 ?"                           @ 144550.0 Hz
  18. "for %a in (1)do set b=%a"            @  45492.5 Hz
  19. "for /f %a in ("1")do set b=%a"       @  47242.3 Hz
  20. "ver>nul"                             @   6124.0 Hz
  21. "echo off>a.t"                        @   1956.4 Hz
  22. "echo.>b.t 4>a.t"                     @    850.0 Hz
  23. "echo.>b.t"                           @    971.7 Hz
  24. "if exist xxxx.txt ?"                 @   9893.5 Hz
  25. "for %a in (#.txt)do set x=%a"        @  39622.5 Hz
  26. "rem"                                 @ 351067.8 Hz
  27. "copy/b f.t+g.t f.t>nul"              @    890.4 Hz
  28. "copy f.t+g.t f.t>nul"                @    667.8 Hz
  29. "shift"                               @ 136519.4 Hz
  30. "fc/? >nul"                           @     26.9 Hz
  31. "findstr/? >nul"                      @     28.0 Hz
  32. "find/? >nul"                         @     28.0 Hz
复制代码

TOP

本帖最后由 plp626 于 2012-3-4 12:50 编辑

搞了个单字符转ascii索引值的专用函数,#char2asc;
中文代码页下运行,支持0x01~0x7f
英文代码页下运行,支持0x01~0xff
  1. @ECHO OFF
  2. setlocal enabledelayedexpansion
  3. :: 定义256表,存入#ff
  4. set $f= 0 1 2 3 4 5 6 7 8 9 a b c d e f&set #ff=&for %%a in (!$F!)do set #ff=!#ff!!$f: =%%a!
  5. :: 获取0x00~0x7f ascii表,存入@
  6. CALL ASCMAP.CMD @
  7. rem ------------------------- 内部 -----------------------------
  8. :: 定义#char2asc 函数,入口参数#1,出口参数##;外部依赖全局变量@={ascii码表0x00~0xff};#ff={查表法求字符串长之256位表}
  9. set "#char2asc=(set $1=&for /f "delims=%@:~97,26%" %%a in ("^^!#1^^!:")do if %%a==: set $1=32)&if ^!#1^!==^!@:~10^^,1^! (set ##=10)else for /f "delims==^^! " %%a in ("^^!#1^^!:")do if %%a==: (if "^^!#1^^!"=="=" (set ##=61)else if "^^!#1^^!"=="^^^^^^!" (set ##=33)else set ##=32)else for /f "eol= delims=" %%b in ("^^!#1^^!")do set #2=^!@:*%%b=^!&set $s=^!#ff^!^!#2^!^!#2^!&set/a##=255-0x^!$s:~-512,2^!+$1&if ⒈ lss 2 set/a ##-=63"
  10. :: 执行#char2asc函数,以字符A做测试
  11. set #1=A
  12. %#char2asc%
  13. echo ascii_code(!#1!)=!##!
  14. pause
复制代码

TOP

回复 26# plp626


    对长变量畏之如虎...不过这确实是一种极大节省循环量的方案,等代码

TOP

本帖最后由 plp626 于 2012-3-3 03:15 编辑

想到一个方法,对单一的字符:

先获取ascii表,比如存放在全局变量@中,(call ascmap.cmd @)

对= ! 这俩字符用if判断下单独处理

然后在获取!@:*%char%=!的长度(这个用查表法,很快),再用255减去这个长度变是char字符的ascii值了;
对于字母的大小写,可用for %%a in (!char!do if %%~dp neq %%a echo 小写
然后对于小写的把最后的索引值+32即可;
这个思路,无需逐一比较是否和ascii表对应字符相等,少去一重循环;

当在437代码也运行时;用ascii表的方法可以处理0x01~0xff的所有字符;
明天贴代码。。。

TOP

回复 24# lllsoslll


    先把能替换的替换了,不方便替换的再用偏移处理也许会很快呢?反正没有宽字符干扰,判断是否字母用 if xx geq a ... 就行了

    呃,试了下纯内部命令的方案,结果跟我预想的不太一样,给出的比值貌似很不正常...

TOP

回复 18# CrLf


    变量名和替换字符不分大小写,变量法或直接替换获取的话,怕是大问题
SOS --- >> lllsoslll@163.com

TOP

回复 20# CrLf


    不错,很好;我一直对usebackq这个bug视作怪物,usebackq的特性我一直就废弃了;
以后用这个^"string^"的转义代替这个特性了;
SOS --- >> lllsoslll@163.com

TOP

回复 21# lllsoslll


    所以才要先对其他特殊字符进行转义处理~

TOP

返回列表