![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-08-08 10:07 |
共 47,811 主题排行 / 349,895 发帖 / 今日 0 篇 / 48,253 会员排行 |
| DOS批处理 & 脚本技术(批处理室) » [讨论]最大限度原样输出含特殊字符的指定行内容 |
| 可打印版本 20,530 / 32 |
| 第1楼 namejm | 发表于 2007-05-17 21:14 |
| 荣誉版主 发帖 1,737 积分 5,226 来自 成都 | |
|
[讨论]最大限度原样输出含特殊字符的指定行内容 在CMD中,对含特殊字符的文本内容的输出处理一直是件很令人头痛的事情:如果要兼容特殊字符,一般会用引号把内容括起来再输出,但是这样一来,就会在所有输出行的首尾都添加了引号,如果对输出后的引号十分在意的话,这个方案就没法实行了。可是,除了这个方案之外,似乎没有别的方案能完美地解决这个难题。(注:完美方案请参考23楼bjsh的代码)
最近这段时间略有闲暇,把这个问题又拿出来思考了一阵子,几经修改,就有了代码1,发出来让大家测试一下: 代码1: 修改自21楼bjsh的代码如下,个人认为是比较完美的方案了: 代码2: 最完美的代码如下(来自23楼bjsh的代码,本人仅作少量改动): 代码3: 测试文件test.txt的内容(请注意:其中一个空行是以空格组成的): 关于代码1及代码2,分析如下: ① 按照一般的思路,for语句中引用变量,都是使用 setlocal enabledelayedexpansion 语句来启用变量延迟功能,但是,这个功能有个致命的缺陷:当要处理的字符串中含有感叹号的时候,会把感叹号对及其之间的所有字符串置换为空,所以,代码1和代码2抛弃 setlocal 方案,使用 call 一段子过程的方案; ② 如果要处理的文本含有奇数个引号的话,echo.%str%>>output.txt 语句将会出错,所以直接把引号替换为特殊的不可见字符之后再输出(也就是在代码中显示出来的黑框);感谢lxmxn的测试和bjsh的分析; ③ 在 :output 子过程中,set "str=%str:^=^^%" 一句必须放在所有替换语句之前,否则,将会把^重复替换,导致结果不准确;感谢 lxmxn 的测试; ④ 普通的 for 语句会忽略以分号打头的行内容,对空行也会忽略掉,所以,使用 findstr .* test.txt 语句来显示所有行(包括空行);delims=: 会把行首的所有冒号抛弃,所以,使用了 call set "str=%%str:*:=%%" 语句来避免这种情况; ⑤ (call echo.%%str%%)>>output.txt 语句中echo后紧跟的点号不能省略,否则,当行内容为空格的时候,输出后的内容将会显示echo的当前状态;使用call语句是为了兼容带引号的行;使用括号是为了能正确处理行尾是以空格分隔的单独的1~9这九个数字。 ⑥ :output 标签段之所以不用 for %%i in (^^ ^> ^< ^| ^&) do call set "str=%%str:%%i=^%%i%%" 这样的语句,是因为这条替换语句并不能正确替换,看来for语句中的 call 延迟机制确实有点让人费解。 关于代码3,由于水平有限,只能做点肤浅而模糊的分析:在这段代码中,利用变量延迟功能来完整地获取特殊字符,并在适当的时候终止变量延迟,以避免因变量延迟过度而造成字符串被识别为变量的问题,实际上,这还是CMD预处理机制在起作用。值得注意的是,setlocal 语句的位置不能与 set 语句做调换,否则,仍然会导致感叹号被识别为变量引用符号,从而被抛弃掉。 [ Last edited by namejm on 2007-8-14 at 09:27 PM ] |
|
| 第2楼 lxmxn | 发表于 2007-05-17 22:44 |
| 版主 发帖 4,938 积分 11,386 | |
|
感谢 namejm 兄的原创,在工作这么忙的情况下还可以顾及论坛,实感欣慰。
经过短暂的测试发现没有任何输出错误。 [ Last edited by lxmxn on 2007-5-17 at 11:16 PM ] |
|
| 第3楼 ieutk | 发表于 2007-05-17 23:25 |
| 初级用户 发帖 48 积分 107 | |
|
好东东,可惜看不懂啊!
|
|
| 第4楼 zh159 | 发表于 2007-05-18 00:11 |
| 金牌会员 发帖 1,467 积分 3,687 | |
|
除了引号,其他的其实都好办
|
|
| 第5楼 bjsh | 发表于 2007-05-18 08:54 |
| 银牌会员 发帖 621 积分 2,000 | |
|
以前也写过类似的:
和namejm兄的差不多; 不过没考虑过某一行都是空格的情况; 最后一句是抄namejm的; echo.%var%的用法实在妙极. 这个解决了"问题; 诸位也帮忙测试下; |
|
| 第6楼 lxmxn | 发表于 2007-05-18 12:36 |
| 版主 发帖 4,938 积分 11,386 | |
|
To bjsh:
测试发现点小问题,请看下面我的测试文本。 test.txt
屏幕显示
|
|
| 第7楼 bjsh | 发表于 2007-05-18 12:53 |
| 银牌会员 发帖 621 积分 2,000 | |
|
唉;三个引号的问题啊;
就好像 echo fsdg"dsgsa"gds" >55.txt 不会写到55.txt里一样; 我在想想吧; 难道真得非写成不可见字符. |
|
| 第8楼 ttyp | 发表于 2007-05-18 13:07 |
| 初级用户 发帖 84 积分 180 | |
|
结果不对啊
aoueo ;euou%^> ::::aeui :::E2uo alejou 3<o2io| ^aue||%ou !aue! !str!auoeu!ueo && ueyi^^^^aueuo2 =^ 第一行“变成乱码,多了最后一行 |
|
| 第9楼 lxmxn | 发表于 2007-05-18 13:15 |
| 版主 发帖 4,938 积分 11,386 | |
|
To ttyp:
第一行的 " 是楼主故意变成那个特殊字符的。 你的测试文本是不是复制楼主的测试文本啊? 我这里测试完全正常。 |
|
| 第10楼 ttyp | 发表于 2007-05-18 13:21 |
| 初级用户 发帖 84 积分 180 | |
|
是复制的,第一行开始没看清楚。
但是最后多一行很奇怪 我的系统是W2K+SP4 |
|
| 第11楼 namejm | 发表于 2007-05-18 13:26 |
| 荣誉版主 发帖 1,737 积分 5,226 来自 成都 | |
Originally posted by bjsh at 2007-5-18 12:53: 经过测试,应该是引号为奇数个的时候才会有这种情况,这是 call 语句调用子过程的时候 echo 语句的一大缺陷,可能只有替换为其他字符才行。 顶楼的代码已经精简了部分语句,set "str=%~1" 完全没有必要存在,呵呵,我的思路复杂过头了。 [ Last edited by namejm on 2007-5-18 at 01:47 PM ] |
|
| 第12楼 ttyp | 发表于 2007-05-18 13:27 |
| 初级用户 发帖 84 积分 180 | |
|
哦,明白了,是我一直在测试P处理,注释了EXIT导致的
|
|
| 第13楼 bjsh | 发表于 2007-05-18 13:49 |
| 银牌会员 发帖 621 积分 2,000 | |
Originally posted by namejm at 2007-5-18 01:26 PM: 是的;是奇数个的时候这样; echo dsg^"sdgsad^"gdgasdg^" >5.txt 就可以了; 其实"也算特殊字符了; 重新修改一下 再测试看还有什么问题 |
|
| 第14楼 bjsh | 发表于 2007-05-18 14:08 |
| 银牌会员 发帖 621 积分 2,000 | |
test.txt内容
发现两者的不同了吗? 前者 显示 此时不应有 > 而后者只是利用for把那段字符转换为%a再赋值给var;就不会报错了; 有意思啊; |
|
| 第15楼 namejm | 发表于 2007-05-18 14:09 |
| 荣誉版主 发帖 1,737 积分 5,226 来自 成都 | |
|
当引号为奇数个的时候,echo的结果不会有什么错误,但是,当引号个数为偶数个的时候,就会出错了。解决的办法是 echo.%var% 改为 call echo.%%var%%,但是这样一来,如果测试内容为 ~ ! @ # $ % ^ & * ( () " ok " No " a>a 的时候,会把最后一个引号之后的所有内容都抛弃掉,原因暂时不明。
———————————————————————————————— 以上言论属于使用的测试代码有误,导致结论出错。 [ Last edited by namejm on 2007-5-18 at 02:53 PM ] |
|
| 1 2 3 下一页 |
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |