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

回复 15# CrLf



恩;
只是大略消除;而且比值的思想是假定电脑配置和环境的变化,使得echo off耗时和代码耗时成正比例变化的;事实上应该不是线性关系;
姑且用近似线性关系来消除偏差;毕竟二者都是随配置提升耗时减少的,单调性一致;


因为求比值的时候,echo off是100000次;代码任务是500次;
最后给代码任务的耗时乘以200;
比值的结果后两位数都是不精确的位数;
SOS --- >> lllsoslll@163.com

TOP

回复 15# CrLf


    想知道如何利用预处理把等号替换为空格
SOS --- >> lllsoslll@163.com

TOP

本帖最后由 CrLf 于 2012-3-2 17:49 编辑

回复 17# lllsoslll


    前不久写过将空格替换为几乎任意字符的高兼容性方案:
  1. @echo off
  2. set str=bbs.bathome.net=abc=123=ABC=@#$=test========
  3. rem 设置源字符串
  4. set 要替换的字符=[#]
  5. set "空="
  6. set "k= "
  7. set "t= "   ;此处引号内的内容为 t=tab制表符
  8. rem 初始化设置
  9. setlocal enabledelayedexpansion
  10. set str=!str:"=""!
  11. rem 将引号倍增,迫使所有字符均在引号对之外
  12. for %%a in (^^ ^& ^| ^( ^) ^< ^> ";" ",") do set "str=!str:%%~a=^^^%%~a!"
  13. rem 替换特殊字符
  14. endlocal&set "str=%str:!=^^!%"
  15. rem 关闭变量延迟,同时保留 str 变量
  16. set "str=%str: =!t!%"   ;此处引号内的内容为 str:tab制表符=!t!
  17. rem 分别替换制表符为变量 !t!
  18. for /f "delims=" %%a in (""%str: =!k!%"") do set str=%%~a
  19. rem 核心语句,替换空格为变量 !k! 后,利用等号在 for 中是分隔符的性质使其被预处理为空格
  20. setlocal enabledelayedexpansion
  21. set "str=!str: =%要替换的字符%!"
  22. rem 完成替换
  23. set "str=!空!%str%"
  24. rem 完成 !k!=空格、!t!=tab制表符 以及 ^ 的消隐,!空! 变量是用于在 %str% 不含 ! 号时触发二次转义
  25. set str=!str:""="!
  26. rem 引号减半,还原现场
  27. echo !str!
  28. rem 输出结果
  29. pause
复制代码
但是因为在 powerbat 的方案中,除了 = 与 ! 之外所有字符都被处理成 asc 了,所以可以这样:
  1. @echo off&setlocal enalbedelayedexpansion
  2. rem 运行环境
  3. rem [[[[[此行代表 powerbat 的方案实现代码]]]]]
  4. endlocal&set str=%str:!=33 %
  5. rem 关闭变量延迟,替换感叹号
  6. set str=%str: =space%
  7. rem 替换空格为 space
  8. for /f "delims=" %%a in (""%str%"") do set "str=%%~a"
  9. rem 替换等号为空格
  10. set str=%str: =32 %
  11. rem 替换空格(原来是等号)为 32
  12. set str=%str:space= %
  13. rem 替换 space 为空格
  14. echo %str%
  15. pause
复制代码

TOP

回复 18# CrLf

一直以来,
    for /f "delims=" %%a in (""..........."")do ......
还有
   for /f "usebackq" ...
在xp中被认为是cmd for /f 的bug(提示找不到文件。。乱码。。);

我这里xp,你那个代码如果把.net与abc之间的等号,换成两个等号,即:
bbs.bathome.net==abc=123====ABC=@#$=test========
这个bug就犯了;

是不是win7修复了这个bug;

另外,我的这里连续的多个等号被当做一个等号替换了;
SOS --- >> lllsoslll@163.com

TOP

本帖最后由 CrLf 于 2012-3-2 18:47 编辑

回复 19# lllsoslll


    测试了一下,xp 下也能替换,但是我之前没有注意到连续的多个等号确实被替换为单个空格了,嗯,看来还是只能老老实实逐字判断

TOP

回复 18# CrLf


    还有一点,当usebackq不犯的时候,
for /f "delims=" %%a in (""string"")do ............
预处理string时,不仅把=视作空格,像参数分割符(= 、,、;、tab)都被视作空格;

(xp系统)
SOS --- >> lllsoslll@163.com

TOP

回复 21# lllsoslll


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

TOP

回复 20# CrLf


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

TOP

回复 18# CrLf


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

TOP

回复 24# lllsoslll


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

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

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

回复 26# plp626


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

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

本帖最后由 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-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

返回列表