目录
使用的系统:(注:以下的探究过程均属于该计算机)
发现问题
最近学习批处理时,因手误打错了一个数字,然后发现了一个问题(引起深思......):
@echo off
echo 计时器准备就绪
echo 按键开始
pause >nul
echo 请等待约5秒
ping 127.1 -n 5 >nul 3>nul
echo 时间到
echo 按键退出
pause >nul
本来想弄个简单的计时器,结果程序未显示“时间到”和“按键退出”的字样,后来检查时发现
"ping 127.1 -n >nul 2>nul"打成了"ping 127.1 -n >nul 3>nul"
猜测原因
尝试1
改回来后,不禁有些疑问,于是又在命令提示符(cmd)中进行几次测试:
echo. >nul 3>nul
echo hello world
echo hi world
分别依次键入以上的代码,显而易见,之后的“hello world”和“hi world”被屏蔽了
试着输入
echo on
结果并未恢复
由此可见,“>nul 3>nul”并非等价于“echo off”。
尝试2
在尝试“echo off”无效后,我试着故意键入一些代码(正确的错误的都有),如“cls”“abcd”等,发现若为错误代码将会报错,正确的反而没有反应(例如:"cls"会清屏失败)
由此可见,批处理屏蔽了“正确的命令”而不执行,但是遇到“错误的命令”会报错。
查询资料
在网上搜索“>nul 3>nul”,发现早已经有人发现了这现象,并给出了解释(句柄备份)
(原文链接在参考资料处,有兴趣的可以去看一下)
这里列举一下句柄:(注:下表的“STD”即“Standard”,意思为“标准”)
句柄 | STDIN | STDOUT | STDERR | UNDEFINED |
句柄号 | 0 | 1 | 2 | 3~9 |
说明 | 标准输入 (默认:从键盘输入) | 标准输出 (默认:输出到命令提示符窗口) | 标准错误输出 (默认:输出到命令提示符窗口) | 未定义的句柄 (需要由用户或应用程序自行定义) |
分析
下面拿个简单的例子来说明:
pause>nul
后面的“>nul”的作用就是屏蔽了 pause 命令的默认输出 “请按任意键继续. . .”
以上是简单的描述,而实际的过程可没那么简单
首先确定重定向符号为 >
接着检查句柄号,发现没有,控制台为其加上默认句柄 1,此时变成 pause 1>nul
由于句柄 1 的默认指向 con,此时要被临时设定为指向 nul,为了之后取回原来的指向,所以要
对 1 的指向进行备份(备份原则:备份到“句柄3~9”中的第一个空句柄中),备份到句柄 3,备份过后临时设定 1 指向 nul
到这时这条语句才被执行(效果就是批处理暂停),然后只有一个下划线闪来闪去。
后面的是重点:还款原则:我有欠条,你必须得还我钱。
执行完后 1 要取回原来的指向
1 的指向在上面被备份到 3
不管 3 的指向有没有改变 1 要取回它的指向来 (还款原则)
取回后 1 指向 con
3 的指向被取走
由于 3 没有备份
所以恢复到原来的状态(即:“空”状态,无指向)
至此整个过程描述完毕
可以发现这时的情况与最初是相同的
所有句柄的指向都是其默认值。
特别的
echo hello >nul >hi.txt >prn >con
在上面的例子中,“>nul”“>hi.txt”“>prn”“>con” 因为都是使用句柄1,所有前面的会被后面的取代,可以理解为只看最后一个使用句柄1的“>con”
即:单一命令行重复使用相同的句柄时,遵循“覆盖原则”:前面的会被后面的取代
echo hello 1<&3 >nul
同样的,在上面的例子中,会以“>nul”为准,即屏蔽hello(不显示hello)
应用
屏蔽错误(可用于批处理或cmd终端)
形式:命令+2>nul 3>nul
例如:
cls 2>nul 3>nul
解决办法(不完全)
分析过后,我也得出来一些结论:
对于“>nul 3>nul”的问题,解决办法治标不治本,可以输入“命令+>con 4>con”,例如:
echo.>con 4>con
当然,如果你刚开始输入的是“命令+>nul 2>nul 3>nul”(效果:无论命令是否正确,都屏蔽回显)
那么,就得输入“命令+>con 2>con 3>con 4>con”了
总之,具体问题具体分析。
缺陷
前面也已经提及了这解决办法“治标不治本”,那么有哪些缺陷呢?
(注:以下缺陷的“造成原因”及其“完美处理办法”尚待解决)
缺陷1
一旦你键入了“>con 3>con”,即使你键入“>con 4>con”,也会有一个明显的特点(大概率出现)
当你输入“cls”命令时,不会清除屏幕
而且还会显示一个“♀ ”(象征女生的符号,也是金星的符号)
猜测:可能是有句柄转换引起的编码错误
已尝试的方法:
1.转义:使用"转义符号^"后,缺陷1未消除
2.批处理:在批处理(.bat)文件中,缺陷1未消除
这一点对大多数人可能毫无影响,但是对强迫症可就有些不友好了(例如笔者本人)
缺陷2
使用后,会对未定义的句柄进行定义,(句柄0~9会有对应的">con"或">nul"标签)
在某些时候可能会影响重定向符的效果
不过,也不必太过担心。如果“编写的批处理文件很简单,没有涉及到复杂的重定向过程”或者“对类似的代码语句多加注意”,一般也不会造成太大的影响
最佳策略
如果不是在处理重要的批处理文件,遇到这种问题的最佳策略无非是:
及时保存(备份文件)——>修改错误的代码——>重新打开文件——>避免同样的错误
是的,看起来很简单,因为对“句柄”的修改一般不会一直有效(就像一次性的环境变量一样)
及时备份,修改错误的部分,便又可以继续使用了
参考资料
——(全篇完)