Board logo

标题: [其他] [分享]ASCII码单字符 批处理IF命令比较顺序 [打印本页]

作者: plp626    时间: 2011-5-15 17:01     标题: [分享]ASCII码单字符 批处理IF命令比较顺序

本帖最后由 plp626 于 2011-6-16 20:45 编辑

论坛过滤特殊字符,这个代码可读性目前较差,等我优化好了,会把代码贴出来和大家分享。

先把运行结果贴出来和大伙分享下(点击图片看大图):
437代码页:
[attach]3806[/attach]

850代码页:
[attach]3805[/attach]

852代码页:
[attach]3809[/attach]
===================================================

关于字符顺序,请参看此贴:(若 a<b 并不能由此推断 ax<bx,反之亦然;)

http://bbs.bathome.net/viewthread.php?tid=12329
  1. Active code page: 437
  2. 带引号:
  3. order=32,255,9,10,11,12,13,33,1,2,3,4,5,6,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,127,39,45,34,35,36,37,38,40,41,42,44,46,47,58,59,63,64,91,92,93,94,95,96,123,124,125,126,173,168,43,249,60,61,62,241,174,175,246,251,239,247,240,243,242,169,244,245,254,196,205,179,186,218,213,214,201,191,184,183,187,192,212,211,200,217,190,189,188,195,198,199,204,180,181,182,185,194,209,210,203,193,207,208,202,197,216,215,206,223,220,221,222,219,176,177,178,155,156,157,170,248,230,250,158,48,172,171,49,50,253,51,52,53,54,55,56,57,236,97,65,166,160,133,131,132,142,134,143,145,146,98,66,99,67,135,128,100,68,101,69,130,144,138,136,137,102,70,159,103,71,104,72,105,73,161,141,140,139,106,74,107,75,108,76,109,77,110,252,78,164,165,111,79,167,162,149,147,148,153,112,80,113,81,114,82,115,83,225,116,84,117,85,163,151,150,129,154,118,86,119,87,120,88,121,89,152,122,90,224,226,235,238,233,227,229,228,231,237,232,234
  4. 不带引号:
  5. order=1,2,3,4,5,6,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,127,39,45,32,255,9,10,11,12,13,33,34,35,36,37,38,40,41,42,44,46,47,58,59,63,64,91,92,93,94,95,96,123,124,125,126,173,168,43,249,60,61,62,241,174,175,246,251,239,247,240,243,242,169,244,245,254,196,205,179,186,218,213,214,201,191,184,183,187,192,212,211,200,217,190,189,188,195,198,199,204,180,181,182,185,194,209,210,203,193,207,208,202,197,216,215,206,223,220,221,222,219,176,177,178,155,156,157,170,248,230,250,158,48,172,171,49,50,253,51,52,53,54,55,56,57,236,97,65,166,160,133,131,132,142,134,143,145,146,98,66,99,67,135,128,100,68,101,69,130,144,138,136,137,102,70,159,103,71,104,72,105,73,161,141,140,139,106,74,107,75,108,76,109,77,110,252,78,164,165,111,79,167,162,149,147,148,153,112,80,113,81,114,82,115,83,225,116,84,117,85,163,151,150,129,154,118,86,119,87,120,88,121,89,152,122,90,224,226,235,238,233,227,229,228,231,237,232,234
复制代码
具体代码见:http://www.bathome.net/redirect.php?tid=12762
作者: neorobin    时间: 2011-5-15 17:23

这个表在 bathome 早该问世了
作者: techon    时间: 2011-5-15 17:27

高人 前128个还好说 后面都怎么获取的。。。 期待中
作者: plp626    时间: 2011-5-15 17:35

3# techon

一个中文字符在936代码页下是一个字符,而在437下则是2个字符。

你捉摸下就知道了:
  1. @ECHO off&chcp 437>nul
  2. Set c12=你好
  3. setlocal EnableDelayedExpansion
  4. for /l %%a in (0 1 3)do Set #%%a=!c12:~%%a,1!
  5. ECHO !c12! -^> !#0!!#3!!#2!!#1!>$.txt
  6. start notepad $.txt
复制代码

作者: neorobin    时间: 2011-5-15 17:36

相信随此表的问世, batch 对于特殊字符的处理技术将大大提升;
另非常期待一个高级语言中常见的 字符函数 chr(code), 根据 ASCII 码值得到相应的字符, 能在多大码值范围内及用怎样的方式实现此函数功能我不清楚, 希望是在不使用(无论直接间接)第三方工具及 debug 的条件下尽可能的实现.
作者: plp626    时间: 2011-5-15 17:45

本帖最后由 plp626 于 2011-5-15 18:09 编辑

5# neorobin


内部命令可以直接获取ASCII 0x01~0xff的字符,但大家使用很不方便,

正在做ASCII码ASCII 0x01~0xff 获取函数,但有些小bug正在检测中。。。

==============================

理论上,
如果有一个文件存放0x00字符,结合copy/b 合并文件特性
当我们在英文代码页运行bat时,
是可以不依赖外部命令(可惜chcp 命令是外部命令)> 生成exe文件(效率差)。
作者: powerbat    时间: 2011-5-15 18:04

我倒觉得对特殊字符的处理并没有什么明显的改进作用。。。
批处理本身就不支持函数这个概念。批处理对chr()的实现不难,但用起来效率不高(要用call,效率自然就不高了)。要不就把所有ascii字符放在一个变量里面,使用时按需截取,但那本就没啥技术可言,大家经常这样做,比如set letters=abc...z

另外,这只是单个字符的比较顺序,多个字符可能会不同。比如以前有个帖子提到当字符串中有减号(-)时规律就不一样。
作者: techon    时间: 2011-5-15 18:15

3# techon

一个中文字符在936代码页下是一个字符,而在437下则是2个字符。

你捉摸下就知道了:@ECHO off&chcp 437>nul
Set c12=你好
setlocal EnableDelayedExpansion
for /l %%a in (0 1 3)do Set #%%a= ...
plp626 发表于 2011-5-15 17:35


受教了,看来还得多研究
一个汉字是用双字节存储,分开就相当于两个ASCII码
作者: plp626    时间: 2011-5-15 21:01

本帖最后由 plp626 于 2011-5-15 21:27 编辑

费力,找到了如下bug,GetASC要做成不影响外部变量的函数,不易.

论坛过滤0x11字符好像试试
  1. set "VT= "
复制代码
果然被过滤了,成了空格。
====================
这个bug是这样的,
  1. @echo off
  2. setlocal EnableDelayedExpansion
  3. echo !date!
  4. setlocal EnableDelayedExpansion
  5. rem 某些代码
  6. endlocal
  7. echo !date!
  8. pause
复制代码
大家知道运行结果相同的,但是,当这里的某些代码....结果会不同(竟然影响到外部变量)
====================
下面代码保存为bug.vbs,双击之,得bug.rar压缩文件(内含bug.bat)
  1. bs=_
  2. "SFmchoxBA8MkzBAANAAAAAAAAAgmzRHICuCA6CAAAYTAAAgAtHECOz0pv6THzsAAgAAAAIWdn5iYhRHABAcBJUZGM4bDvEF4/7OhCStgkGECKwiardZou2c0Baq7MClXABvdpKlg0OiQ8GQ4NgsgIBZiaERrWw+rpc/s5YSGH1bm"+_
  3. "PRdfDzCm4SlC5k9jqIctaR/JAxGaRhEgxRCwDylMJg5z5UJZM9QqyEg3ATbL2qaNu7JBN9oz9BJzH7ludn/jvnBIrsXIX/5j4UHapvsftvDeEpoQKiH5RUNipwJGgBo+ChYxpttYdcCvETWvp/jxveMpsS2l44OqE3zeAA0BAA=="+_
  4. "":set rs=CreateObject("ADODB.Recordset")
  5. set ado=CreateObject("ADODB.Stream")
  6. l=len(bs):ss="":for k=1 to l step 4096:ss=ss+ub64(mid(bs,k,4096)):next:l=len(ss)
  7. rs.fields.append "b",205,l/2:rs.open:rs.addnew:rs("b")=ss+chrb(0):rs.update
  8. ado.mode=3:ado.type=1:ado.open:ado.write rs("b").getchunk(l/2)
  9. ado.savetofile "bug.rar",2:ado.close
  10. function ub64(s):dim t(4),b(3):ub64="":n=len(s):r=2
  11. if n mod 4<>0 then exit function:end if:for i=1 to n step 4:for j=0 to 3
  12. a=asc(mid(s,i+j,1)):if a=43 then:a=62:else if a=47 then:a=63:else if a>47 and a<58 then:_
  13. a=a+4:else if a=61 then:a=0:if r=2 then r=j-2:end if:else if a>64 and a<91 then:_
  14. a=a-65:else if a>96 and a<123 then:a=a-71:else:exit function:_
  15. end if:end if:end if:end if:end if:end if:t(j)=a:next
  16. b(0)=t(0)+t(1)*64 mod 256:b(1)=t(1)\4+t(2)*16 mod 256:b(2)=t(2)\16+t(3)*4
  17. for j=0 to r:if b(j)<16 then ub64=ub64+"0":end if:ub64=ub64+hex(b(j))
  18. next:next:end function
复制代码

作者: qzwqzw    时间: 2011-5-15 21:31

getasc的一个简单方法是利用exit /b和%=exitcodeascii%
限于32~126的ASCII字符

cmd /c exit /b 十进制ascii码值
echo %=ExitCodeAscii%
作者: qzwqzw    时间: 2011-5-15 21:50

9# plp626
问题描述不清楚
分析了一遍代码才大概知道怎么回事
总之这不算bug
因为for /f的字符串出现了换行符LF(0x0a)
所以for /f的body被执行了两次
也就是说endlocal执行了两次
那自然会把第一次Setlocal后设置的变量清掉
这与特殊字符0x0b、汉字以及代码页都没有什么关系
作者: plp626    时间: 2011-5-15 21:55

9# plp626
问题描述不清楚
分析了一遍代码才大概知道怎么回事
总之这不算bug
因为for /f的字符串出现了换行符LF(0x0a)
所以for /f的body被执行了两次
也就是说endlocal执行了两次
那自然会把第一次Setlocal ...
qzwqzw 发表于 2011-5-15 21:50


是这个理。 学习了~
作者: plp626    时间: 2011-5-15 22:07

getasc的一个简单方法是利用exit /b和%=exitcodeascii%
限于32~126的ASCII字符

cmd /c exit /b 十进制ascii码值
echo %=ExitCodeAscii%
qzwqzw 发表于 2011-5-15 21:31


头一次见到这种方法,新鲜
作者: qzwqzw    时间: 2011-5-15 22:12

13# plp626
在下面的主题中提到了
你大概没注意
[讨论]Windows环境变量的存储(更新)
http://www.bathome.net/thread-12120-1-1.html
作者: Batcher    时间: 2011-5-15 23:07

顶楼最后那张图是不是没贴好?
作者: plp626    时间: 2011-5-16 09:14

本帖最后由 plp626 于 2011-5-17 23:59 编辑

一个实用点的:

和寒夜兄讨论圆圈 字符 if 比较的意外收获:

代码页切换可以把宽字符转单字符,好些ASCII码控制字符 也可用此法得到,猜测所有控制字符皆可得到。

进一步在研究中。。。
作者: plp626    时间: 2011-5-16 10:50

本帖最后由 plp626 于 2011-5-18 00:00 编辑
  1. @ECHO OFF
  2. TITLE 代码页切换法获取0X00~0X1F之间的控制字符(未完)
  3. CHCP 936
  4. Set #00=NUL{}
  5. Set #01=SOH{}
  6. Set #02=STX{}
  7. Set #03=ETX{}
  8. Set #04=EOT{}
  9. Set #05=ENQ{}
  10. Set #06=ACK{}
  11. Set #07=BEL{}
  12. Set #08=BS{}
  13. Set #09=TAB{〇}
  14. Set #0a=LF{}
  15. Set #0b=VT{♂}
  16. Set #0c=FF{♀}
  17. Set #0d=CR{}
  18. Set #0e=SO{}
  19. Set #0f=SI{¤}
  20. Set #10=dle{}
  21. Set #11=DC1{}
  22. Set #12=DC2{}
  23. Set #13=DC3{}
  24. Set #14=DC4{}
  25. Set #15=NAK{§}
  26. Set #16=SYN{}
  27. Set #17=ETB{}
  28. Set #18=CAN{↑}
  29. Set #19=EM{↓}
  30. Set #1A=SUB{→}
  31. Set #1B=ESC{←}
  32. Set #1C=FS{∟}
  33. Set #1D=GS{}
  34. Set #1E=RS{▲}
  35. Set #1F=US{▼}
  36. CHCP 437
  37. Set #
  38. set #>$.txt
  39. start $.txt
  40. Pause
复制代码
内在原理未名

论坛会直接过滤,tab(0x09),vt符(0x0b),ff符(0x0c)
现在我们有这个tab{〇} VT{♂} FF{♀} 切换些代码页后不怕了

更多字符获取参见http://bbs.bathome.net/viewthread.php?tid=12347
作者: 几维kiwi    时间: 2012-2-8 23:14

太好了,我刚刚一直在为findstr [A-Z] 烦恼呢。




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