批处理中一些比较琐碎、但又有价值的一些知识点
本节学习有关批处理的一些比较琐碎、但又比较有价值的一些知识,运用这些知识后,才有条件更好的实现的批处理的功能,并能使批处理摆脱黑白世界而显得更加多姿多彩。废话少说,开讲啦~
环境变量
所谓环境变量,实际上就是C语言里面的“变量”的意思。批处理的变量可以分为两类,由系统定义的系统变量和由用户根据需要自定义的用户变量。
系统变量
批处理的一些变量是由操作系统事先定义好的,可以适用于任何批处理,我们称这些特殊的变量为“系统变量”。系统变量有很多个,包括硬件类、操作系统类、文件路径类、系统时间类等。要查看所有的系统变量,请新打开一个cmd窗口,输入set回车即可。对几个比较常用的变量解释如下:
- ComputerName 计算机名,即右键 我的电脑–属性–计算机名 选项卡中的“完整的计算机名称”
- ComSpec cmd.exe完整路径名
- HomeDrive 系统分区盘符,一般都是C盘,故而HomeDrive=C:
- Path 可执行文件默认搜索路径。这个东东非常重要!待会儿单独讲解…
- ProgramFiles 就是系统的Program Files的路径啦,一般都是C:/Program Files,这就是安装软件时默认的安装路径了
- Prompt 个性化设置cmd提示符的必备武器!不过,我没怎么用过~
- SystemDrive 包含系统根目录的分区,其实就是HomeDrive了
- SystemRoot 系统根目录路径,一般都是C:/WINDOWS
- Temp、Tmp 文件、程序等可使用的临时目录,默认是C:/WINDOWS/Temp或Tmp。几乎所有的程序在运行时都会在这个目录里面“临时”写入文件。一般情况下,程序写入的临时文件都应该被该程序删除,可惜的是,大部分的程序都很健忘,导致这个文件夹占据的空间越来越大,自然也就使我们的系统增肥喽。所以,我们要把它修改到其他分区,并且时时的清理里面的临时文件。
- UserName 当前用户名,即所登陆的账户名
- UserProfile 当前用户的配置目录,一般都是C:/Documents and Settings/%UserName%。默认情况下,我们的桌面就是这个目录下面的“桌面”文件夹;我的文档就是这个目录下面的“My Documents”文件夹。所以啦,往桌面上或我的文档里面放东西就是放到这个文件夹下面了,也就是放到C盘了,重装系统时要覆盖C盘内容的,所以桌面上或我的文档里面的东西当然就会Gone with the Wind了~解决方法有两个,一是保持良好的习惯,不把重要文件放到这两个地方;二是,修改默认设置,将这两个文件夹都移到其他分区。
- WinDir 操作系统路径,其实就是SystemRoot了
用户变量
编写批处理程序时,用户根据需要自己定义的变量称之为用户变量。用户变量类似于C语言里面的变量,仅仅在定义该变量的程序中有效。 用户变量由set命令定义,这是批处理中非常非常重要的一个操作,从而使set命令成为批处理里面使用频率最高的几个命令之一。关于set命令的使用,参考set /?,本教程也会在后面对其进行讲解。
变量引用
前面的几节课里面,我们已经看到了如何引用变量,即直接用变量名操作变量,通过”%”或”!”来获取变量的值。其中,只有在for语句里面重复对同一变量多次赋值时才需要使用”!”,并且在使用”!”调用变量时,要首先“启用延迟环境变量扩充”,启动命令为:SetLocal EnableDelayedExpansion
。另外需要说明的是,“启用延迟环境变量扩充”后,所有的”!”都将被视为“取变量值”的特殊符号,即使用”^!”也不能输出符号”!”。若要输出”!”,则需要“停用延迟环境变量扩充”,命令为:SetLocal DisableDelayedExpansion
。
参数
跟C语言类似,在调用函数或其他批处理时可能需要传递参数。批处理的参数传递分为直接和间接两种传递参数的方法。
直接传递
直接传递参数,即在使用call命令时,不使用任何参数,在子函数或子批处理里面直接对主函数(也称父批处理)里面的变量进行修改。这跟汇编语言里面的参数传递方式类似。
直接传递参数举例:
1 | =============================================== |
可以发现,当我们把变量var作为参数赋予子函数:deal后,子函数对var的值进行了修改;当子函数返回后,主函数里面的var的值就已经是子函数里面var被修改后的值了。
该例子中,使用了本节课前面讲到的setlocal enabledelayedexpansion和setlocal disabledelayedexpansion
,前者保证了var在for循环里面能够根据我们的意愿进行处理,后者保证了能够正确输出符号”!”。另外例子中还使用了命令set,利用set对字符串进行了处理。还有一个地方使用了语句goto :eof
,该语句相当于C语言里面的return或汇编语言里面的RET,即子程序返回命令。需要说明的是,当子函数本身就在批处理文件的末尾的话,我们是可以省略这句话的,比如将此例的goto :eof
删除是不会产生任何影响的。
间接传递
间接传递参数,即在使用call命令时,在其后面添加参数,形如call {[:label][ChildBatch]} Parameter1 Parameter2 ... ParameterN
。这跟C语言里面传递参数的格式类似。不同于C语言,批处理中的子函数不需要定义形参,更不需要指定参数的个数。传递过来的参数,在子函数或子批处理里面是以%1~%9
的形式表示的,即%1~%9
分别表示传递过来的第1~9个参数。
1 | =============================================== |
通过这个例子就可以清晰的看到%n参数表示法的用法。参数列表中包含空格的依旧要用双引号(“)引起来;另外,也可以看到,%0
已经变成了子函数的标号了,而不是父批处理的文件名全称。
区别
这两种参数传递方法本质上是没有区别的,形式上,直接传递直接对原变量进行操作,丢失了原变量的值;间接传递则通过%n对原变量进行了简单的备份,并且通用性更强,即不限定原变量的名称。另外,使用%n还有一个非常大的好处,就是可以通过%~*i
来加强处理变量的能力。关于%~*i
,详细内容参见for /?
。
针对二者的差别,可以根据情况决定使用哪种传递方式:
- 作为参数的变量名固定、且在子函数中不需要对其进行备份的情况下,使用直接传递法;
- 若将子函数作为一个通用的程序模块,以适应于对不同变量的处理,或者作为参数的变量不需要备份时,使用间接传递法。
具体使用哪种方法,还需根据实际情况或使用习惯进行选择。
返回值
有些命令在执行之后将会返回一定的错误值(errorlevel
),可以通过errorlevel
的值判断命令执行的状况。这点类似于C语言里面的exit(num),num就是错误代码。
获取返回值errorlevel
的方法就是,在执行命令后,立马调用返回值errorlevel
,如echo %errorlevel%
或者if %errorlevel%==1
等命令。
errorlevel举例:
1 | =============================================== |
上面例子中,由于第一成功的删除了注册表,导致第二次因为找不到注册表而宣告失败。同时我们也看到了errorlevel
的使用方法,即if errorlevel 0
和if %errorlevel%==0
是一样的。也许你注意到了,里面还有个笑脸呢~O(∩_∩)O哈哈~
这就是ASCII码啦,后面跟你讲啊…
一般情况下,程序或命令成功执行时,返回的errorlevel是0,错误时返回1或更高的值。当然,有些命令是没有返回值的,这点需要注意。
嗯,有没有想起前面有个类似的东西啊?对了,那就是||和&&了,这两个符号就是根据errorlevel的值来进行逻辑判断的~
用户交互
批处理,黑框白字是它最著名的特征。虽然当初DOS为人们使用计算机做出了莫大的贡献,但在Windows盛行的今天,人们已经疏远并且惧怕那个黑色的窗口了。微软为了让先天有着批量处理“体力活”能力的DOS避免“冷酷”,便于接近,特意提供了几个小命令,加强批处理的用户交互功能。
视窗
首先我们要DIY它的窗口。使用命令:color、mode、msg。
- 设置窗口背景色和字体颜色by color。详细内容参见color /?。
- 设置窗口大小by “MODE CON [COLS=c] [LINES=n]”,cols即宽度,lines即高度。
- GUI交互窗口by msg。详细内容参见msg /?。
视窗DIY举例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30===============================================
@echo off
set a=10
set b=0
:tex
set /a a+=3
set /a b+=1
mode con cols=%a% lines=%b%
if %a% lss 60 goto :tex
echo O(∩_∩)O 天天快乐 O(∩_∩)O
set a=15,a6,2e,d0,34,8b,4f,9d,5e
for %%i in (%a%) do (
ping -n 2 127.1>nul
color %%i
)
for %%i in (%a%,%a%) do (
ping -n 1 127.1>nul
color %%i
)
>>ms.txt echo */. . . * .
>>ms.txt echo ./* . [] * __
>>ms.txt echo */ . .//~~~~~~~~~~~~'/. ^|◆
>>ms.txt echo /* ,/,..,/,...........,/.◆
>>ms.txt echo ^|^| ..▎# ▎田 田 ▎ ^| ▎◆
>>ms.txt echo ^|^| ^&^&▎ ▎ ▎'^|'▎ o
>>ms.txt echo ^|^| ##■■■■■■■■■■〓
msg %username% /w /time:3600 <ms.txt
del ms.txt
pause
===============================================
声音
呵呵,是不是注意到了批处理没有声音呐?闲话不说,直接做实验吧 _
1 | =============================================== |
speak好像不能讲中文呐~
此处错误,如果tts安装了中文引擎是可以讲中文的。
此外,这个就是调用vbs的方法:vbscript:createobject("sapi.spvoice").speak("Hello!")
控制
在运行批处理的过程中,我们如何干预批处理呢?呵呵,直接点叉叉就可以结束它了!嗯,不错,不过,太野蛮了~
- 暂停批处理:直接按键盘上的Pause键喽
- 终止批处理:组合键Ctrl+C。不过,有时候它好像响应的不太积极啊…
ASCII码
前面的例子中,我们已经使用过一次ASCII码了,也就是那个笑脸。ASCII码是图形化的符号,可以用来点缀我们的批处理的。
在cmd窗口中我们可以通过任意一个字符的ASCII码来输入该字符,比如Ctrl+G
、Ctrl+N
等,字母a-z对应ASCII码的1-26。对于ASCII码大于26的字符,可以通过这个方法来输入:按住Alt键不松,通过小键盘输入ASCII码的十进制值,松开Alt键即可。