Board logo

标题: [文本处理] [分享讨论]批处理0A换行符的获取与功能 [打印本页]

作者: mxxcgzxxx    时间: 2011-7-26 22:56     标题: [分享讨论]批处理0A换行符的获取与功能

本帖最后由 mxxcgzxxx 于 2011-8-2 23:23 编辑

在CrLf 的《批处理利用set /p与重定向输入分行获取文本内容》一文中我对SET/P与PAUSE结合而读取到的0A换行符非常的有兴趣,因此通过测试0A字符的功能与特点,希望能让这个特别的字符派上用场!

首先是这个字符与其他换行符不同之处在于:
1.它不是一个完整的换行符,因此有很大区别,它是存在的,可以看得到的!
2.它在大多数情况下与换行符功能相当,可以获取,可以替换,可以写入函数.但它还能写入文本,却不是以换行形式存在!
3.一般情况下换行符就等同于拆分文本,但0A字符不是,显示时虽然也是分行的,但实际只存在一行文本数据,一个数据的容量也受最大存储量的限制,0A换行符占一个字符位。
4.多数情况下文本中的0A字符都起到换行作用,使用type\FOR\findstr读时都只能以行截取方式读它前后的文本.但在SET/P情况下可以完整的读取到它并保持行的完整性!

由于论坛也不支持显示0A字符,所以只能通过运行程序在文本中体现了,下面就是我的测试程序.

优点:
1、独一无二的分隔符,适合分段式存取数据或数据组中需要应用各种特殊符号的情况,对于数组中字符未知、列数不等的情况尤为好用。
2、可以在TXT格式文本中进行复制粘贴,同样适用于BAT(VBS,JV等未测试)。
(但在写入BAT时要注意0A换行符无法直接用在代码中,可以将值放在代码头部,用(set/p p=)<%0方法读取),具体方法看14楼,感谢lfoqtal的提示
3、在显示数据时用时比普通换行符更少。

缺点:
1、适用文本少,大多数文本格式不支持0A的独立存在,所以应用局限性强
2、现发现只能使用SET/P方式还原,无法使用其他语句进行读取
3、无法使用SET替换回正常符号

大家可以看看生成的文本与显示之间的区别,在1.txt文本中显示的黑块就是0A换行符
  1. :
  2. @echo off
  3. setlocal enabledelayedexpansion
  4. set "e=^!a^!"
  5. ::0A 换行符的获取
  6. (pause&set/p a=)<%0 >nul
  7. set a=!a::=!
  8. ECHO 0A 的显示
  9. echo 1-0A!a!0A
  10. echo 2-0A%a%0A
  11. echo 3-0A%e%0A
  12. pause
  13. ECHO 将0A 换行符单独保存入一个文本中
  14. echo.!a!>1.txt
  15. ECHO 0A字符在函数中的转嫁
  16. set b=123!a!456
  17. set b=!b!!a!999
  18. echo B=!b!
  19. set c=aaa#bbb#ccc
  20. set c=%c:#=!a!%
  21. echo C=!c!
  22. ECHO 将带有0A字符的值写入文本
  23. echo B=!b!>>1.txt
  24. echo C=!c!>>1.txt
  25. pause
  26. ECHO 利用0A字符的换行功能,在FOR中进行文本读取
  27. for /f %%a in ("!b!") do echo B= %%a
  28. for %%a in (!c!) do echo C= %%a
  29. pause
  30. ECHO type命令查看带有0A字符文本的情况
  31. type 1.txt
  32. pause
  33. ECHO for /f 命令读取带有0A字符文本的情况
  34. for /f "delims=" %%a in (1.txt) do echo %%a
  35. pause
  36. ECHO findstr 判断0A文本的能力
  37. findstr "456" 1.txt
  38. pause
  39. ECHO 用set/p方式读取文本,由于第一行的0A 与第一句换行符的0D0A相配,使第二个0A下沉到第二句句首
  40. (for /l %%a in (1 1 3) do set/p d0A%%a=)<1.txt
  41. set d0A
  42. pause
  43. ECHO 替换0A换行符为普通字符,总是失败
  44. set b=%b:!a!=QQ%
  45. set c=!c:%e%=666!
  46. echo B=!b!
  47. echo C=!c!
  48. pause
复制代码
利用0A分段式保存数据
  1. :
  2. @echo off
  3. setlocal enabledelayedexpansion
  4. cd.>2.txt
  5. (pause&set/p a=)<%0 >nul
  6. set a=!a::=!
  7. for /l %%i in (1 1 3) do (
  8.     set/a b=%%i+1
  9.     for /l %%a in (1 1 !b!) do (
  10.          set/p 数据%%i%%a=%%i组%%a列,请输入任意文本:
  11.          set 数组%%i=!数组%%i!!a!!数据%%i%%a!
  12.          )
  13.     echo !数组%%i!>>2.txt
  14.     )
  15. cls
  16. echo 显示文本
  17. type 2.txt
  18. pause
  19. cls
  20. ::读取文本
  21. (for /l %%i in (1 1 3) do set/p 文组%%i=)<2.txt
  22. ::比对一
  23. echo 组对比
  24. set 数组
  25. set 文组
  26. pause
复制代码
希望大家也一起来测试它的能力,看看在哪些方面能巧妙的利用上
作者: CUer    时间: 2011-7-26 23:08

它不是一个完整的换行符?其实不然。
Windows的记事本遇到0D0A(回车,换行)你才能看到它换行,UNIX就不一样了。
回车,换行,这是打字机时代遗留的产物啦。
作者: hfg1977    时间: 2011-7-26 23:08

我们都知道,在windows/dos 下标准的回车符由 0a0d 组成.
^J   10 LF  馈行(line feed)在大多数UNIX 系统和变异系统中用来结束行;
^K  12 FF  馈页(form feed)用来使打印机馈出一页;
^M  13 CR  回车(carriage return)在Mac OS, OS-9, FLEX 和CP/M-80派生的系统中,包括DOS,用于结束文本行;

虽然可以在文本下看到一个黑点,但0a依旧归属于不可见字符.
作者: tmplinshi    时间: 2011-7-26 23:17

我们都知道,在windows/dos 下标准的回车符由 0a0d 组成.
^J   10 LF  馈行(line feed)在大多数UNIX 系统和 ...
hfg1977 发表于 2011-7-26 23:08


是 0D0A
作者: CrLf    时间: 2011-7-26 23:21

本帖最后由 CrLf 于 2011-7-26 23:23 编辑

这个...不是打击楼主的热情,但是其实早就有更简洁的办法了:
  1. set 换行符=^
  2. cmd /v /c echo abc!换行符!123
  3. ::目前获取换行符最简方案
复制代码
详见此贴:
http://bbs.bathome.net/viewthrea ... %B7%FB%2Bzqz0012005

另外,记事本无法看到单独的换行符,但是你可以用左右键“感觉”到有一个不可见字符,用 more 或者 for /f+echo 均可将其还原成配套的回车换行
作者: mxxcgzxxx    时间: 2011-7-26 23:33

回复 3# hfg1977


    嗯这个我倒是没细想,我马上将1.TXT中的文本复制到了DOC文档中,发现单个0A字符WORD根本不接受,而一行中有0A时当成换行符,拆分文本,而且不是认别为↓
作者: mxxcgzxxx    时间: 2011-7-26 23:35

本帖最后由 mxxcgzxxx 于 2011-7-26 23:56 编辑

回复 5# CrLf


    我知道,但那种方法无法进行存储,一旦存入文本就分行了就不再是一个完整的内容了,所以这个字符才有它存在的价值
而且不只是可见还是真实存在的,可以像退格符一样复制粘贴到你的代码中

如这样利用它来存取数据组
  1. :
  2. @echo off
  3. setlocal enabledelayedexpansion
  4. cd.>2.txt
  5. (pause&set/p a=)<%0 >nul
  6. set a=!a::=!
  7. set 数组1=123!a!456!a!789
  8. set 数组2=789!a!48789654!a!121!a!123132!a!1231!a!1321!a!3132!a!13
  9. echo !数组1!>>2.txt
  10. echo !数组2!>>2.txt
  11. ::读取数组
  12. (for /l %%a in (1 1 2) do set/p 数组%%a=)<2.txt
  13. for /l %%a in (1 1 2) do (
  14.            set b=0
  15.            for %%1 in (!数组%%a!) do (
  16.                    set/a b+=1
  17.                    set 数据%%a!b!=%%1
  18.                    )
  19.             )
  20. set 数据
  21. pause
复制代码
是不是少了一个替换符号的过程,也不会因为内容的未知性而苦想用什么符号来分隔这些数据进行存取
作者: tmplinshi    时间: 2011-7-27 00:04

本帖最后由 tmplinshi 于 2011-7-27 00:05 编辑
回复  CrLf


    可以像退格符一样复制粘贴到你的代码中 ...
mxxcgzxxx 发表于 2011-7-26 23:35



大部分文本编辑器不会显示“黑块”,例如 EmEditor、AkelPad。
作者: mxxcgzxxx    时间: 2011-7-27 00:11

回复 8# tmplinshi


    嗯,我也发现了它的局限性很大,在BAT与TXT中还能用,到其它文本中就不太行了
  另外除了set/P可以还原外别无他法,这也是一个软肋
作者: Hello123World    时间: 2011-7-29 13:23

http://jl453625978.blog.163.com/ ... 705201162912240760/

刚查了一下资料。
作者: mxxcgzxxx    时间: 2011-7-29 19:43

本帖最后由 mxxcgzxxx 于 2011-7-29 21:00 编辑

回复 10# Hello123World

感谢技术的支持,看样子只要是单独的换行或回车在WINDOWS下都是显示一个黑块呀

但我很奇怪那个例子里的56背后的/n/r应该在windows下应该是一个完整的换行符了,结果却出现了两个黑块,这里还有出入啊

因为从PAUSE截取的情况来看不论是0A 0D 还是0D 0A的组合都会在TXT中产生换行作用(在下面的链接里有讨论过),
但在你给的链接里所说的例子中却不会,
说明Linux下的/n/r并不等同于windows下的0D 0A,
http://www.bathome.net/redirect.php?goto=findpost&ptid=13327&pid=86638&fromuid=35352
作者: lfoqtal    时间: 2011-8-2 10:58

本帖最后由 lfoqtal 于 2011-8-2 11:00 编辑

测试了下,不论是在占位、存储容量大小上与 set a=^ 是一样的没有区别
倒是可以单行将代码写入文本这点还不错,
但我试了下直接复制写入BAT进行赋值好像不行也:
  1. @echo off &setlocal enabledelayedexpansion
  2. set "a=456[0A]123"
  3. echo !a!
  4. pause
复制代码
到0A时就出错了后面的没法写入加^转义也不行
是不是我哪错了?

另外有点小发现,在显示用完整换行符的值和0A换行符的值时显示的时间会有差别,
0A换行符显示得更快些,这个倒是个大优点
3000组数据会相差0.4秒
作者: mxxcgzxxx    时间: 2011-8-2 20:15

本帖最后由 mxxcgzxxx 于 2011-8-2 22:34 编辑

回复 12# lfoqtal


    容量有测过是一样的,不是算半个,倒是速度没测过!
   用普通换行符可以用肉眼看出换行过程,而0A是瞬间的,但是测试速度却不稳定,在>nul隐藏情况下差别不大,
   在正常显示出值时是有差别,一个函数时字符数达到极限8000多时,每两个字一个换行符,3000多个换行符差别平均在0.04钞左右

  
换行: -91 -63  0A: -106 -57
换行: -69 5943  0A: -62 -64
换行: -38 5943  0A: -50 -36
换行: -38 5943  0A: -34 -36
换行: -38 5943  0A: -34 -36
换行: -38 -63  0A: -34 -36
换行: -67 -63  0A: -64 -66
换行: -68 -65  0A: -64 -64
换行: -67 -64  0A: -64 -64
换行: -67 -63  0A: -64 -64
换行: -68 -62  0A: -63 -66
换行: -67 -62  0A: -64 -66
换行: -68 -64  0A: -62 -64
换行: -69 -62  0A: -64 -66
换行: -67 -64  0A: -64 -65
换行: -67 -64  0A: -64 -64
换行: -69 -62  0A: -62 -66
换行: -68 -62  0A: -64 -64
换行: -67 -61  0A: -62 -66
换行: -67 -62  0A: -64 -64

第一列为正常显示时间,第二列为>nul隐藏显示时间
不知道运行计算赋值时会不会有速度影响,要进一步测试
作者: mxxcgzxxx    时间: 2011-8-2 23:12

回复 12# lfoqtal


    确实在BAT中直接粘贴0A换行符在代码中无法赋值,加^或双引号都无法进行转义
  所以只能用这个方法了,非常感谢提供信息
  1. 456[0A]123
  2. @echo off &setlocal enabledelayedexpansion
  3. cls
  4. (set/p a=)<%0
  5. echo !a!
  6. pause
复制代码

作者: tiandyoin    时间: 2023-2-22 17:23

本帖最后由 tiandyoin 于 2023-2-22 17:26 编辑

00:
  1. @
  2. ::0A 换行符的获取
  3. @echo off
  4. setlocal enabledelayedexpansion
  5. echo "00"=%0
  6. echo "01"=%1
  7. echo 0A@ 的显示
  8. set "e=^!a^!"
  9. rem 将开头两行赋值给 a
  10. (pause&set/p a=)<%0 >nul
  11. echo 0-XX!a!YY
  12. set a=!a:@=!
  13. ECHO 0A 的显示
  14. echo 1-XX!a!YY
  15. rem 使用 %% 获取失败
  16. echo 2-XX%a%YY
  17. rem 使用 %% 获取成功,是变量的扩展的扩展,其中还使用了延迟变量方式。
  18. echo 3-XX%e%YY
  19. pause
  20. goto :eof
复制代码
作者,你开头一行多了个空格,可能因为论坛会消除空行,你用空格填充一行,但你没给大众说明一下。
还有,我觉得挺奇的,输出输出的脚本路径,赋值却能得到换行符。
输出:
  1. "00"="C:\获取回车符和换行符.bat"
  2. "01"=
  3. 0A@ 的显示
  4. 0-XX
  5. @YY
  6. 0A 的显示
  7. 1-XX
  8. YY
  9. 2-XX
  10. 3-XX
  11. YY
复制代码





欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2