Board logo

标题: [文本处理] 【已解决】@的复杂用法与疑惑 [打印本页]

作者: 踏沙行    时间: 2018-7-5 10:18     标题: 【已解决】@的复杂用法与疑惑

本帖最后由 踏沙行 于 2018-7-20 12:32 编辑

@的用法,按常规说法是:本行命令不显示(在控制台)
但在下面的实例中,这一用法却非常困惑,请大神指点
例:在test02.txt中,保存以下内容:
  1. aldskfj                                zsdlf    dblkj     
  2. 不灭星辰诀                               巅峰黑客
  3. xxdl DDty                              123ft
  4. 重生之修真霸道  张天扬            至尊无赖
复制代码
1、完整显示test02.txt的内容,代码如下:
  1. 1.方法一:
  2. @echo off
  3. for /f "delims=" %%i in (test02.txt) do echo.%%i
  4. pause
  5. 1.方法二:
  6. @echo off
  7. for /f "delims=" %%i in (test02.txt) do @echo.%%i
  8. pause
复制代码
【问】方法二使用了@echo %%i,为什么还显示结果呢?

2、对test02.txt内容排序
  1. 2.方法一:echo前加@
  2. @echo off
  3. (for /f "delims=" %%i in (test02.txt) do @echo.%%i) |sort
  4. pause
  5. ====结果=========
  6. aldskfj                                zsdlf    dblkj
  7. xxdl DDty                              123ft
  8. 不灭星辰诀                               巅峰黑客
  9. 重生之修真霸道  张天扬            至尊无赖
复制代码
  1. 2.方法二:echo前不加@
  2. @echo off
  3. (for /f "delims=" %%i in (test02.txt) do echo.%%i) |sort
  4. pause
  5. ========结果========
  6. aldskfj                                zsdlf    dblkj
  7. I:\>echo.aldskfj                                zsdlf    dblkj
  8. I:\>echo.xxdl DDty                              123ft
  9. I:\>echo.不灭星辰诀                               巅峰黑客
  10. I:\>echo.重生之修真霸道  张天扬            至尊无赖
  11. xxdl DDty                              123ft
  12. 不灭星辰诀                               巅峰黑客
  13. 重生之修真霸道  张天扬            至尊无赖
复制代码
【区别】方法二未在echo前加@,不仅显示了多个命令行,而且开始还有好多空行。
【疑惑】for 使用的是逐行输出,所以输出结果会出现4行命令,但是:
(1)为什么开头还有好多空行?
(2)为什么4行命令会出现在输出内容的中间部分,而不是一行命令,一行输出结果呢?

3、对test02.txt的所有字段排序(即以空格分开的字段排序)
  1. 3.方法一,do后面加括号
  2. @echo off
  3. (for /f "delims=" %%i in (test02.txt) do (@for %%a in (%%i) do @echo.%%a)) |sort
  4. pause
  5. =====结果========
  6. 123ft
  7. aldskfj
  8. dblkj
  9. DDty
  10. I:\>()
  11. I:\>()
  12. I:\>()
  13. I:\>()
  14. xxdl
  15. zsdlf
  16. 不灭星辰诀
  17. 巅峰黑客
  18. 张天扬
  19. 至尊无赖
  20. 重生之修真霸道
复制代码
  1. 3.方法二:do后面不加括号
  2. @echo off
  3. (for /f "delims=" %%i in (test02.txt) do @for %%a in (%%i) do @echo.%%a) |sort
  4. pause
  5. =======结果正确======
  6. 123ft
  7. aldskfj
  8. dblkj
  9. DDty
  10. xxdl
  11. zsdlf
  12. 不灭星辰诀
  13. 巅峰黑客
  14. 张天扬
  15. 至尊无赖
  16. 重生之修真霸道
复制代码
  1. 3.方法三:使用括号,但在括号前加@
  2. @echo off
  3. (for /f "delims=" %%i in (test02.txt) do @(for %%a in (%%i) do @echo.%%a)) |sort
  4. pause
  5. ===结果同上:正确=====
复制代码
【疑惑】
1、3.方法二中,在in后面有两个do,又加使用括号,cmd为什么还能正确解析呢?
2、3.方法一中,为什么仅仅在第一个do前面加了括号,就多出来好多空行和命令行呢?
3、@的作用,不应该是作用本行,而应该是作用本命令、本括号吗?
作者: 狄钦dQ    时间: 2018-7-5 23:59

本帖最后由 狄钦dQ 于 2018-7-6 00:29 编辑

对于1:楼主怕是误解@的意思,作用是关闭命令自身回显。
先科普下echo命令和@用法:http://www.bathome.net/thread-13860-1-1.html
for语句内 @echo 是没有意义的。批处理开头@echo off 相当于在每一个命令前补上一个@,从而实现关闭了所有命令的回显。
括号()+管道符|的组合:
  1. @echo off
  2. ( for /l %%i in (1,1,5) do echo bathome ) | find "a"
  3. echo ============================
  4. ( for /l %%i in (1,1,5) do echo bathome ) | find "r"
  5. echo ============================
  6. ( for /l %%i in (1,1,5) do echo bathome ) | find "z"
  7. pause
复制代码
以上代码请细心品味,再删去@echo off重新品味。
解读:第2个和第3个for语句应该结果相同,然而第2个却能看到echo的输出结果,此处应该涉及到批处理的一堵高墙,预处理机制。(能力有限,不做深入分析)
括号将for语句整个包裹,而管道符| 连接着find命令,这是一句完整的语句。该复合语句的含义是:进行5次循环,同时执行echo输出,成功后,将结果传给find命令执行,再得到最后的匹配结果。
  1. D:\Users\Desktop>(for /L %i in (1 1 5) do echo bathome  ) | find "a"
  2. D:\Users\Desktop>echo bathome
  3. bathome
  4. D:\Users\Desktop>echo bathome
  5. bathome
  6. D:\Users\Desktop>echo bathome
  7. bathome
  8. D:\Users\Desktop>echo bathome
  9. bathome
  10. D:\Users\Desktop>echo bathome
  11. bathome
复制代码
可见以上过程产生了两次结果。上例中第2和3条for语句得到的结果不同,虽然是在find命令得到echo的输出结果才显示匹配结果。
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /l %%i in (1,1,5) do echo bathome | find "a"
  4. echo ============================
  5. for /l %%i in (1,1,5) do echo bathome | find "r"
  6. echo ============================
  7. for /l %%i in (1,1,5) do echo bathome
  8. pause
复制代码
同样删去@echo off再品味。
几个回答:
1. 为何多个很多空格?
echo输出末尾带换行符。sort命令把每次echo的换行符也做了排序,多少次echo就有多少次换行。这也涉及到"括号的正确使用"。
2. 括号()和@关闭回显的关系?
@ 是作用于单个命令,严格来说不是语句,更不是一行。对于复合语句,@只关闭后面的第一条命令的回显,也无法关闭括号内的所有命令回显,括号内之后的命令还是会显示。
楼主的例2方法一之所以能显示echo语句,正是由于整个for语句被括号包裹,而echo off只是在括号外加了一个@,但这只是关闭一个命令回显,其后仍然会显示。
以上仅代表本人看法,未完待续,等待大佬做权威解答。




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