标题: 扩展ASCII码字符集0x00~0xff 批处理获取函数 [打印本页]
作者: plp626 时间: 2011-5-17 20:15 标题: 扩展ASCII码字符集0x00~0xff 批处理获取函数
问题描述:
特殊字符有其特殊用途,像制表符,退格符,响铃,回车,换行,文件结束符;
但其赋值需要特殊方法;另外,在坛友跟帖,贴出代码时又有不少字符被论坛直接过滤
比如:制表符(0x09),回车符(0x0d),换行符(0x0a),vt符(0x0b),ff符(0c),欧元符(0x80),还有那个和unicode文件头有关的0xff字符,另外文件结束符(0x1a)不能直接在bat源代码中赋值,要用特殊方法;
这些问题批处理自身会如何解决?
----------------------------------------------------------------------------
原帖给出了字符集获取的背景和思路;因为叙述比较繁琐,考虑到大家阅读方便,现在打包;看重思路的坛友可在此下载原帖备份文件;
[attach]4786[/attach]
这里直接给出问题的解决方案:
- @echo off||code by plp&title ascii 0x01~0xff 对照表
- setlocal enabledelayedexpansion
- 2>nul call ascmap /437 $ ||call:getasc $
- echo.
- set p=&set lf=!$:~0x0A,1!
- set hx=0 1 2 3 4 5 6 7 8 9 A B C D E F
- for %%a in (%hx%)do for %%b in (%hx%)do set "$%%a%%b=!$:~0x%%a%%b,1!!$:~9,1!"
- for %%a in (
- "00=<NUL>" "07=<BEL>" "08=<BS>" "09=<TAB>" "0A=<LF>" "0D=<CR>" "20=<SP>"
- )do set "$%%~a!$:~9,1!"
-
- for %%a in (a b c d)do set "p=!p!^!d%%a^! 0x%%%%a%%z ^!$%%%%a%%z^!!$B3:~,1! "
- for /f "tokens=1-4" %%a in ("0 2 4 6!lf!1 3 5 7!lf!8 A C E!lf!9 B D F")do (
- (if %%a==8 echo.)&for %%z in (%hx%)do (
- set/a da=0x%%a%%z,db=0x%%b%%z,dc=0x%%c%%z,dd=0x%%d%%z
- for %%a in (a b c d)do set d%%a= !d%%a!&set d%%a=!d%%a:~-3!
- echo %p:~0,-2%
- )
- )
- if "%~0"=="%~f0" set/p=
- goto:eof
-
- :getasc <$|#|@|_|{|}|[|]> // 将0x01~0xff255个字符存放在%1变量内
- chcp 936>nul
- set %1gbk=币市布弄清分标圈唉上下同名后小成民怒易笔耕化吗战则刚猛夜思舞鸟简闹出读导能图绿
- chcp 437>nul
- Set %1=&cmd /u/c echo !%1gbk!>%tmp%\%1gbk.tmp&set/p %1gbk=<%tmp%\%1gbk.tmp
- for /l %%a in (0,2,76)do Set %1=!%1!!%1gbk:~%%a,1!
- set %1= !%1:~,31! ^^!"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^_`abcdefghijklmnopqrstuvwxyz{|}~!%1:~-8,1!亗儎厗噲墛媽崕彁憭摂晼棙櫄洔潪煚、¥ウЖ┆辈炒刀犯购患骄坷谅媚牌侨墒颂臀闲岩釉罩棕仝圮蒉哙徕沅彐玷殛腱眍镳耱篝貊鼬!%1:~-7!
复制代码
然后是0x00字符的获取:
- :: 获取ascii 0x00 字符
- cmd /u/cecho.>$.tmp
- findstr/vrc:$ $.tmp>0x00.txt
复制代码
上面两个代码,说明批处理内部命令+chcp+findstr(这两个外部命令基本保险)实现了所有ascii字符的处理和存储;
这为批处理内部命令对字符的处理大大拓宽道路,使得批处理更“独立”,也使娱乐批处理更上一层楼
为了减少临时文件的生产和减少外部命令chcp,findstr的使用,从而提升代码执行效率,
本贴为此特定制了ascmap函数:
下载ascmap.cmd(ver 1.01.02): [attach]4295[/attach]
1.2版本更新说明:兼容 在未开启变量延迟的情形下对ascmap.cmd的调用
下载ascmap.cmd(ver 1.2): [attach]5066[/attach]
游客身份不能下载的,使用下面代码双击生成精简版 ascmap.cmd:
- @echo off||生产ascmap.cmd 1.2
- setlocal enabledelayedexpansion&chcp 936>nul
- :: 生产首行ascii表
- set gbk=币市布弄清分标圈唉上下同名后小成民怒易笔耕化吗战则刚猛夜思舞鸟简闹出读导能图绿
- chcp 437>nul&cmd /u/c echo !gbk!>gbk.tmp
- set/p gbk=<gbk.tmp
- if exist ascmap.cmd del/f/a ascmap.cmd
- Set s=&for /l %%a in (0,2,76)do Set s=!s!!gbk:~%%a,1!
- set $= !s:~,31! ^^!"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^_`abcdefghijklmnopqrstuvwxyz{|}~!s:~-8,1!亗儎厗噲墛媽崕彁憭摂晼棙櫄洔潪煚、¥ウЖ┆辈炒刀犯购患骄坷谅媚牌侨墒颂臀闲岩釉罩棕仝圮蒉哙徕沅彐玷殛腱眍镳耱篝貊鼬!s:~-7!
- echo :!$:~1,9!^^^^!$:~10,16!^^^^!$:~26,1!!$:~27!>ascmap.cmd
- for /f "delims=:" %%a in ('findstr/nb :@: %~s0')do more +%%a<%~s0>>ascmap.cmd
- :: 添加NUL字符到文件尾部
- cmd/u/cecho.>gbk.tmp
- findstr/vrc:$ gbk.tmp>$00.tmp
- copy/b ascmap.cmd+$00.tmp ascmap.cmd>nul
- attrib +R ascmap.cmd
- ECHO File ascmap.cmd is created.
- del gbk.tmp $00.tmp
- if "%~0"=="%~f0" pause
- :@:
- :: get ascmap; version 1.2 ; code by plp
- :: 请在 http://www.bathome.net/viewthread.php?tid=12347 下载完整版本获取帮助信息
-
- @for /f "delims=/" %%a in ("%~1")do @if /%%a.==%1. chcp %%a>nul&&shift/1||exit/b 1
- @if %1. neq . (
- set/p %1=<"%~f0"
- if !!.==. (set %1= !%1:~1,9!!%1:~11,16!!%1:~28!) ELSE (
- setlocal enabledelayedexpansion&set tab=!%1:~9,1!
- for /f "tokens=1-3" %%a in ("!%1:~1,8!!%1:~12,15!!%1:~28!")do @(
- endlocal&set %1= %%a!%tab%^
-
- %%b %%c
- )
- )
- )
- @if %2. neq . findstr/vrc:$ "%~f0" >"%~2"
复制代码
在此将研究该问题得到的副产品罗列如下,
不同代码页下字符个数的不同:
- :: 依此原理可以:
- :: 判断一个gbk编码下的字符串含有宽字符的个数
- :: 求计算字符串的字节数(没有临时文件实用)
- @ECHO off&chcp 437>nul
- Set c12=你好
- setlocal EnableDelayedExpansion
- for /l %%a in (0 1 3)do Set #%%a=!c12:~%%a,1!
- ECHO !c12! -^> !#0!!#3!!#2!!#1!>$.txt
- start notepad $.txt
复制代码
常用特殊字符的较简洁内部命令通用获取方法:
- :: 获取文件结束符0x1A
- copy nul+nul sub.txt
-
- :: 获取“退格符”, 变量b_b的值为:退格符空格退格符(0x08 0x20 0x08)
- for /F %%a in ('"prompt $h&for %%b in (1) do rem"')do Set b_b=%%a
-
- :: 脚本中获取回车符 0x0d
- for /f %%a in ('copy/z %~s0 nul')do set $0d=%%a
-
- :: 脚本中获取换行符 0x0a, ^字符后空两行;
- set $0a=^
-
- ::脚本中获取换页符 0x0c,
- for /f %%a in ('cls')do set $0c=%%a
-
- :: 936(中文)代码页下 cmd/u法获取制表符 0x09 (0x01~0x1F皆可用此法获取)
- for /f "delims=U" %%a in ('cmd/u/cecho 唉')do set $09=%%a
-
- :: cmd/u法获取unicode文件头0xfffe(0x80后的字符要切换代码页)
- chcp 936
- Set gbk=绿图
- chcp 437
- for /f "tokens=1-2delims=~V" %%a in ('cmd/u/cecho %gbk%')do set Un=%%a%%b
-
- :: 代码页切换法获取制表符
- chcp 936
- set $07=〇
- chcp 437
- set $07 >tab.txt
复制代码
XP 5.1.2600下"快速"获取01~1f的截取低位字节法
总共31个汉字,依次对应31个特殊字符 (注意,此法win7 失效):
- :: 响铃符0x07 --> 标
- :: 退格符0x08 --> 圈
- :: 制表符0x09 --> 唉
- :: 换行符0x0a --> 上
- :: 回车符0x0d --> 名
- :: 比如单行获取换行符:for %%a in (上:)do set $=%%~da&set $0a=!$:~,1!
-
- @echo off&setlocal enabledelayedexpansion
- for %%a in (
- 币 市 布, 弄 清 分 标 圈
- 唉, 上 下 同 名, 后 小 成
- 民 怒, 易 笔 耕 化 吗
- 战 则 刚 猛,夜 思 舞 鸟
- )do set/a n+=1&for %%b in (%%a:)do echo %%a -!n!- %%~db
- pause
复制代码
这里要说的是这个代码页切换法的获取制表符的原理,
大多低位特殊字符对应的宽字符还未找到:(该问题待续。。)
- @ECHO OFF
- TITLE 代码页切换法获取0X00~0X1F之间的控制字符(未完)
- CHCP 936
- Set $00=NUL{}
- Set $01=SOH{}
- Set $02=STX{}
- Set $03=ETX{}
- Set $04=EOT{}
- Set $05=ENQ{}
- Set $06=ACK{}
- Set $07=BEL{}
- Set $08=BS{}
- Set $09=TAB{〇}
- Set $0a=LF{}
- Set $0b=VT{♂}
- Set $0c=FF{♀}
- Set $0d=CR{}
- Set $0e=SO{}
- Set $0f=SI{¤}
- Set $10=dle{}
- Set $11=DC1{}
- Set $12=DC2{}
- Set $13=DC3{}
- Set $14=DC4{}
- Set $15=NAK{§}
- Set $16=SYN{}
- Set $17=ETB{}
- Set $18=CAN{↑}
- Set $19=EM{↓}
- Set $1A=SUB{→}
- Set $1B=ESC{←}
- Set $1C=FS{∟}
- Set $1D=GS{}
- Set $1E=RS{▲}
- Set $1F=US{▼}
- CHCP 437
- Set $
- set $>$.txt
- start $.txt
- Pause
复制代码
一些应用:
http://www.bathome.net/thread-12314-1-1.html
http://www.bathome.net/thread-12349-1-1.html
http://www.bathome.net/thread-12762-1-2.html
0x00字符获取思路参考:http://www.bathome.net/thread-12284-2-1.html
Thanks to: 寒夜孤星 CRLF zqz batman neorobin qzwqzw 。。。
作者: batman 时间: 2011-5-17 22:03
技术的确令人叹为观止,实用性有待挖掘和提升。。。
作者: wankoilz 时间: 2011-5-17 23:09
本帖最后由 wankoilz 于 2011-5-19 19:16 编辑
不知道那些特殊符号楼主是如何处理的...佩服!
恶补了一下编码知识基本算是明白了...
作者: plp626 时间: 2011-5-19 17:17
本帖最后由 plp626 于 2011-6-15 19:17 编辑
- ::获取控制符的gbk2unicode方案
- ::以回车符为例演示如下(“名”--unicode编码为540d)
- @ECHO off&setlocal EnableDelayedExpansion
- for /f %%a in ('cmd/u/cecho 名')do set un=%%a
- :: 获取回车符0x0D并存放在变量$0d中
- Set $0d=!un:~0,1!
- Set test=abcd!$0d!##
- ECHO !test!
- set test>$0d.txt
- start $0d.txt
- pause
复制代码
- ::获取unicode文件头的gbk2unicode方案及其测试代码:
- @ECHO off&setlocal EnableDelayedExpansion
- Set gbk=绿图
- chcp 437>nul
- for /f %%a in ('cmd/u/cecho !gbk!')do set un=%%a
- ::获取unicode文件头字符0xFF 0xFE,并存放在变量head中
- Set head=!un:~0,1!!un:~2,1!
- Set head
- set/p=!head!`O}Y<nul>$tmp.txt
- ::"你好" 对应的unicode编码为4f60 597d
- start $tmp.txt
- pause
复制代码
下面列出常用汉字unicode编码的低位值供查阅:复制代码
作者: wankoilz 时间: 2011-5-19 19:28
楼上发这个出来是想做个查表法的编码转换么?
作者: CrLf 时间: 2011-5-19 20:13
plp_00=刀 阀 怀 开 攀 退 稀 销 需 言 耀 一 匀 最
plp_01=币 持 愁 丁 封 搁 阁 洁 老 码 企 省 谁 送 锁 态 威
plp_02=昂 蜂 挂 搂 茂 漂 适 市 堂 异 脂
plp_03=布 吃 调 范 考 七 弃 球 刃 逃 娃
plp_04=锄 ...
plp626 发表于 2011-5-19 17:17
原来那个帖子的素材是从这里捣鼓过去的...
作者: batman 时间: 2011-5-19 20:39
plp626终于又回到拆分法上来了,呵呵。。。
作者: CrLf 时间: 2011-5-19 23:04
8# batman
可是“在中文代码页下”应该用不了拆分法吧...很纳闷,等待正解
作者: CrLf 时间: 2011-5-19 23:10
看到plp兄的拆分法之前曾寄希望于cmd /u,但是测试后发现不行,内容全变了,除此以外啥想法都没有...
作者: guo135956 时间: 2011-5-22 16:34
无效代码页
系统找不到指定的文件。
eof=→
626
〇#
请按任意键继续. . .
作者: plp626 时间: 2011-5-22 16:44
11# guo135956
你的,详细环境和测试代码是?
作者: playinthesky 时间: 2011-7-2 23:10
12# plp626
WINDOWS 7下貌似不能调用。
作者: CrLf 时间: 2011-8-7 22:42
回复 13# playinthesky
我也是 win7 系统,可以正常运行呀...以下为半角转全角代码,试试正常不:- @echo off&setlocal enabledelayedexpansion
- chcp 437
- call ascmap $
- (for /l %%a in (32 1 126) do (
- set /a "n=%%a+128"
- for /f "eol= delims=" %%b in ("!n!") do (
- echo [!$:~%%a,1!=!$:~163,1!!$:~%%b,1!]
- )
- ))>全角字符.txt
- pause
复制代码
作者: Demon 时间: 2012-9-8 23:43
重定向到文件时才是0x00~0xFF,在内存中有部分不属于0x00~0xFF。
作者: amwfjhh 时间: 2014-11-6 11:11
奇思妙想……
晓得拆字方法后可以自己遍历一下需要代码的相关宽字符,再挑一个可以手输的用来作变量截取,再通过代码页车换将宽字符拆成高低字符,这样貌似都不需要cmd /u了,直接chcp就可以实现,只是需要去寻找这些特殊字符,先测试一下看看。
PS:
测试结果,遍历了下0~255*255内的本地化字符,单纯用本地化的DBCS(双字符字集),要取到没有歧义的字符,高位字节必大于0x80,且低字节大于等于0x40即0x814*以上才有不被之前字符重复的有效双字节字符,这即意味着要从双字节里面取需要的值,不管是低字节还是高字节,都有取不到的区间,还是用unicode可行。
有兴趣的同学可以参考下附件的表格。
链接: https://pan.baidu.com/s/1ouycfG6Q5V8u2FVVeayqlg 提取码: iaus
作者: email10t 时间: 2015-4-21 14:53
作者: email10t 时间: 2015-4-21 14:55
作者: email10t 时间: 2015-4-21 14:58
这是一个论坛的漏洞,欧元符号([attach]8580[/attach])被忽略了
作者: Batcher 时间: 2015-4-21 15:12
回复 15# amwfjhh
建议把大附件放到网盘上面
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |