问题描述:
特殊字符有其特殊用途,像制表符,退格符,响铃,回车,换行,文件结束符;
但其赋值需要特殊方法;另外,在坛友跟帖,贴出代码时又有不少字符被论坛直接过滤
比如:制表符(0x09),回车符(0x0d),换行符(0x0a),vt符(0x0b),ff符(0c),欧元符(0x80),还有那个和unicode文件头有关的0xff字符,另外文件结束符(0x1a)不能直接在bat源代码中赋值,要用特殊方法;
这些问题批处理自身会如何解决? ----------------------------------------------------------------------------
原帖给出了字符集获取的背景和思路;因为叙述比较繁琐,考虑到大家阅读方便,现在打包;看重思路的坛友可在此下载原帖备份文件;
这里直接给出问题的解决方案:
- @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):
1.2版本更新说明:兼容 在未开启变量延迟的情形下对ascmap.cmd的调用
下载ascmap.cmd(ver 1.2):
游客身份不能下载的,使用下面代码双击生成精简版 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 。。。 |