特殊字符的处理一直是困扰新手的一大难题,就算是老手,也不敢保证能对各种场合中的特殊字符应付自如,现在给出处理各种特殊字符的方法,供各位参考。
何谓特殊字符?一般而言,我们把已经在cmd中赋予了各种功能的符号称为特殊字符,比如>、>>、<、<<、|、||、&、&&、^、%,另外,在处理文件路径的时候,空格也可以算作特殊字符。
很多人都知道,要正确处理路径中的空格,需要用引号把路径括起来,比如:md "c:\test abc\123"。实际上,只要文件路径中含有特殊字符,则引号对是必须的。
可能还有些人知道,要输出百分号本身,需要在它之前再添加一个百分号,比如,要显示 %abc% 这个字符串,应该写成 echo %%abc%%。
但是,当我们要输出>、<、|之类的特殊符号的时候,大多数人就开始绞尽脑汁了。
首先,我们要请出转义字符^,它能帮我们应付绝大多数的特殊字符。例如,我们要显示>,echo ^>即可;要显示|,echo ^|即可,也就是说,在每个特殊字符前加上转义字符^,就可以对特殊字符进行原样输出了。这次,你会原样输出 aueou>|&a^ueo 之类的字符串了吗?
但是,转义字符^也不能包打天下:当需要输出的是已知的一串或多行字符串的时候,确实可以在每个特殊字符前添加^来原样输出,可是,如果特殊字符的位置不确定,或是我们需要从某个文本中原样读出一串或多行可能含有特殊字符的未知字符串的时候,我们还能用插入转义符号^的办法吗?这显然是行不通的。
或许你已经意识到,就算是对含有特殊符号的路径用引号对括起来以保证处理它的时候不至出错,但是,当要用echo语句显示这个路径的时候,引号对还是会显示出来,这个多余的引号对并不是我们需要的,有时候甚至是我们无法容忍的。
转义字符^无用武之地,引号对也行不通,难道我们就这样彻底绝望了吗?
这次,该for语句隆重出场了。
先看示例:- @echo off
- for /f "delims=" %%i in (test.txt) do (
- set "str=%%i"
- setlocal enabledelayedexpansion
- echo.!str!
- endlocal
- )
- pause
复制代码 test.txt内容如下(已经囊括了特殊字符):
aoueoa & aeo"83
aeouoaeA3ua^|!:>
><||a6^$2oueo
%ae!aoue
在这里,我动用了各种手段以保证特殊字符能够原样显示:
① 用 "delims=" 避免取到的字符串从空格处被截断;
② 用 set "str=%%i" 这样的引号对写法保证把字符串原样赋予变量 str ;
③ 在适当的位置开启变量延迟并在合适的地方终止变量延迟,以保证能原样显示变量 str 的值。在这一点上,很多人,包括很多熟练使用 setlocal enabledelayedexpansion 语句的人,都会忽略一些技术细节,从而不能100%原样显示变量 str 的值:我发现,绝大多数的批处理老鸟,都喜欢在@echo off和for语句之间使用 setlocal enabledelayedexpansion 语句,这是个非常不好的习惯——如果变量的值中含有半角感叹号的话,感叹号将被直接抛弃!正确的做法是:在for语句内部而不是外部开启变量延迟,并在合适的地方用endlocal语句终止延迟——endlocal一定要添加上,这是个好习惯,否则,当 setlocal enabledelayedexpansion 被执行32次之后,将会报错,从而引发后续处理错误。
当然,就算我动用了这么多手段,也不能保证能处理文本中的所有特殊情况:当行首为分号的时候、当存在空行的时候……
如果要处理所有的特殊情况,请使用如下代码:- @echo off
- cd.>output.txt
- for /f "delims=" %%i in ('findstr /n .* test.txt') do (
- set "var=%%i"
- setlocal enabledelayedexpansion
- set var=!var:*:=!
- (echo.!var!)>>output.txt
- endlocal
- )
- start output.txt
复制代码 详细解释请参考本人以前在CN-DOS发的帖子:[讨论]最大限度原样输出含特殊字符的指定行内容。 |