找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 29420|回复: 14

再谈批处理最大原样输出文本字符

[复制链接]
发表于 2011-2-24 10:49:44 | 显示全部楼层 |阅读模式
原文由本人同时发表在个人qq空间:http://user.qzone.qq.com/841615149/blog/1298514537
      其实在cn-dos的《最大原样输出文本字符》一贴中通过各位大哥级人物的共同努力早就解决了这一难题,本人只是以个人的理解再归纳总结一次,以便新人更好地消化吸收。

  首先,我们先来谈谈如何输出带有空行(空行也要输出)的文本。大家知道for命令是默认忽略空行的,也就是说文本中的空行用for.....echo的方式是不会得到输出的。那么如何解决这一问题呢?这时findstr就大显身手了:
  1. @echo offf
  2. for /f "tokens=1,2 delims=:" %%a in ('findstr /n .* a.txt') do echo,%%b
  3. pause>nul
复制代码
  findstr /n .* a.txt能将a.txt的内容全部打印出来,但是前面都加上了行号和:字符,于是我们通过设置:为分隔符就可以将这个输出结果每行分成两列,第一列是行号,第二列就是a.txt原来每行的内容,我们只取第二列即可。事实上这种方法能几乎兼容所有的特殊字符,但它还是存在一个硬伤。大家猜猜是什么呢?其实这个硬伤就在于它是用:字符来做为每行的分隔符,那么当文本内容中含有:字符的时候,:字符将全部视为分隔符,同样只能输出行号后的:字符和文本行第一个:字符之间的内容,这时我们也可以修改上面的代码为:
  1. @echo offf
  2. for /f "tokens=1* delims=:" %%a in ('findstr /n .* a.txt') do echo,%%b
  3. pause>nul
复制代码
  

  但即使如此,还是不能解决a.txt中有的行是以:字符打头的情况(这个打头的:字符将不被输出)。那么,我们又该怎么办呢?大家记不记得set str="%str:*a=%"这个替换方法,就是将str字串符中从打头字符到第一个a字符之间的所有字符替换为空(包含a字符)。我们也可以用这种方法来处理这个讨厌的:字符:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "delims=" %%a in ('findstr /n .* a.txt') do (
  3.      set "str=%%a"
  4.       echo,!str:*:=!
  5. )
  6. pause>nul
复制代码
  哈哈,难缠的:字符终于被彻底征服了。可是,我们可别高兴得太早哦,这时又跳出来一个捣蛋的家伙!。不信的话你拿着上面的代码去处理含有!的文本看,你会发现文本中所有的!没有被输出,如果出现!******!的情况,就连两个!字符间的所有的字符都不会被输出。这是因为开启变量延迟后,!将当做逃逸字符被脱去,而两个!字符之间的字符将被视为变量处理,而输出这个变量的值(空值)。真的是一波刚平一波又起啊,难道这个:字符和!字符是生死冤家,不能被同屏输出?答案肯定是否。是的,我们通过预处理就可以轻松解决这一问题:
  1. @echo off
  2. for /f "delims=" %%a in ('findstr /n .* a.txt') do (
  3.     set "str=%%a"
  4.     setlocal enabledelayedexpansion
  5.     echo,!str:*:=!
  6.     endlocal
  7. )
  8. pause>nul
复制代码
  至此,我们已经完全解决同时正确输出有空行和所有特殊字符(不包括不可见字符)的文本这一问题了。但有一点还要说明一下,就是这个echo,!str:*:=!之所以在echo后面加上,是为了输出空行,而平常时我们常用到echo.!str! echo/!str!这些用法来输出空行,但在这里只能用到,字符才能正确输出,不信的话,大家可以自己测试下。

[ 本帖最后由 batman 于 2011-2-24 11:00 编辑 ]
 楼主| 发表于 2011-2-24 11:13:21 | 显示全部楼层
补充说明:
  如果只是要原样输出文本,建议用type a.txt和findstr .* a.txt即可,
  但如果在原样输出文本,还要对文本字符进行处理的话,就要用
  到本贴所说的方法了。
发表于 2011-2-24 11:49:33 | 显示全部楼层
除了逗号之外,分号和等号也行吧?
发表于 2011-2-24 12:30:35 | 显示全部楼层
刚才测试了一下。除了两位大老的方法外,退格也行。不过得在其前加个空格
  1. setlocal enabledelayedexpansion
  2.     echo !str:*:=!
  3.     endlocal
复制代码
 楼主| 发表于 2011-2-24 14:36:26 | 显示全部楼层

回复 3楼 的帖子

确实分号和等号可以。。。
发表于 2011-2-25 16:24:59 | 显示全部楼层
刚试了下,最后成功显示出来
发表于 2018-8-28 10:44:56 | 显示全部楼层
从第三条涨知识
发表于 2020-7-22 19:36:42 | 显示全部楼层
没想到近来我也用到了原样输出文本的知识,谢谢版主!!!
发表于 2022-11-4 20:46:06 | 显示全部楼层
谢谢楼主,学习了!
发表于 2025-8-6 07:28:15 | 显示全部楼层
echo, echo; echo=貌似不支持以/?开头的行
或者以批处理分隔符加/?开头的行 ,输出时会显示echo的帮助信息
支持/?并且最通用的应该是echo(
只是echo(只有半边括号 ,会影响编辑器的括号匹配 ,看起来怪怪的 ,而且还可能影响阅读 ,得加上点不会执行的来凑够右边括号才行
!str:*:=!这句还是分开来 ,单独弄一句set好 ,能用的echo方式好像会多点

评分

参与人数 1技术 +1 收起 理由
77七 + 1 感谢分享

查看全部评分

发表于 2025-8-6 10:59:09 | 显示全部楼层
本帖最后由 aloha20200628 于 2025-8-7 13:35 编辑


改用 echo.echo/echo\ 均可在命令行上兼容 /? 开头的字符串

  1. echo./?abc123xyz
  2. echo\/?abc123xyz
  3. echo//?abc123xyz
复制代码
针对一楼第4段的脚本代码,可改为如下两个版本均可兼容用 /? 开头的字符串了...

版本之一

  1. @echo off
  2. for /f "delims=" %%a in ('findstr /n .* a.txt') do (
  3.     set "str=%%a"
  4.     setlocal enabledelayedexpansion
  5.     set "_str=!str:*:=!"
  6.     echo.!_str!
  7.     endlocal
  8. )
  9. pause&exit/b
复制代码
版本之二

  1. @echo off
  2. for /f "delims=" %%a in ('findstr /n .* a.txt') do (
  3.     set "str=%%a"
  4.     setlocal enabledelayedexpansion
  5.     echo(!str:*:=!
  6.     endlocal
  7. )
  8. pause&exit/b
复制代码
发表于 2025-8-6 20:04:41 | 显示全部楼层
回复 11# aloha20200628


    版本二第5行那句
    echo(!str:*:=!)
中的右括号 )语法上是跟前面do (那个左括号相匹配的 ,for命令到第5行就结束了 ,因此那个右括号)是需要转义的
应该改成类似下面那样的
echo(!str:*:=!||/ ^)
只要echo命令不是not complete successfully就行  ,还有!和||之间不能有空格 ,不然输出时末尾也会有空格
发表于 2025-8-7 11:18:53 | 显示全部楼层
本帖最后由 77七 于 2025-8-7 11:54 编辑

看了大佬们的讨论,我发现 右括号也能用来注释
  1. rem @echo off
  2. ) &||
  3. echo ()&) (((||
  4. pause
复制代码


执行没有任何反应...

还是有瑕疵,单独执行以下代码的 echo 可以,用在含有括号的复合语句中,还是会引起括号的错误配对
  1. if 1 equ 1 (
  2.         echo(123&)
  3. )
复制代码

做了一点测试
  1. @echo off
  2. %1 cmd /k %0 rem
  3. if 1 equ 1 (
  4.         echo 1)
  5. ) 此行被当作注释行了


  6. echo ----------
  7. echo 正确注释格式
  8. if 1 equ 1 (
  9.         echo 1)
  10. );)


  11. echo ----------
  12. echo 报错。")" ")+分隔符" ")+分隔符+内容" 均为注释,不会被当作可执行文件;右括号+非分隔符被当作可执行文件
  13. if 1 equ 1 (
  14.         echo 1)
  15. ))

  16. pause

复制代码
发表于 2025-8-7 13:01:07 | 显示全部楼层
本帖最后由 aloha20200628 于 2025-8-7 13:09 编辑

回复 12# Five66

确实如此,echo(!str:*:=!) 这行代码还是应改为 echo(!str:*:=!,11楼代码版本二已订正...
发表于 2025-8-7 14:39:52 | 显示全部楼层
回复 13# 77七

实测后的结论似乎是》仅当以前没有与之配对的左括号时,以下两种用法方可使右括号注释其后的字符串,其一是行首即为 ) 且其后须紧随至少一个系统默认分隔符,其二是 ) 可前缀系统默认分隔符且其后须紧随至少一个系统默认分隔符

  1. @echo off
  2. (echo.123)
  3. );我是注释
  4. ),; =        我是注释
  5. echo.abc
  6. ,; =        ),; =        我是注释
  7. pause&exit/b
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-16 22:40 , Processed in 0.023815 second(s), 9 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表