Windows 批处理脚本学习教程

Collected by Clove

第三章:赋值 调用 参数

3.1 赋值

3.1.1 给变量赋予一个文字字符串的值

说到赋值,就得先弄懂 set 这条命令。set 这条命令比较复杂,在命令提示符中键入 set /? 后得到的帮助信息也很多。不过,简单地说,使用 set 跟上变量,再用等号 = 跟上字符串就能简单地给该变量赋值了。例如 set var=Hello world! 。为了确认一下变量 var 的值是否是 Hello world! ,可以用 set var 来查看变量 var 的值。用 set v 可以查看所有以字母 v 开头变量的值。直接输入 set 可以查看所有变量的值。另外,变量两侧加上百分符号 % 用来表示该变量的值(内容)。这样做可以将该变量的值赋给其他变量或是用做计算显示等处理。

3.1.2 给变量赋予一个数值型的值

在 set 后面加上 /a 的参数可以给变量赋予一个数值型的值,例如 set /a var=48 表示将数字48赋给变量var。该数值型的变量是一个32位的整数型数值,即占用4个字节,能表示的数值个数为2的32次方,含正负号,范围为:-2147483648~2147483647。

3.1.3 从外部获得输入的赋值方式

在 set 后面加上 /p 的参数,可以将变量设成用户输入的一行输入。读取输入行之前,显示指定的 提示文字。当然,提示文字也可以是空的。比如 set /p var=请输入一些文字: ,可以显示出一段提示文字"请输入一些文字:"并能将用户输入的信息存到变量var里。/p 的参数还有很多诸如对字符串的替代、提取、增减等功能,具体可以参考 set 的相关帮助信息。

3.1.4 变量的值的赋予、显示、变换、计算等功能

可能此时有些朋友对百分号 % 的理解还处于迷茫状态,对此我们可以做一些实验。首先,就像前文所说的那样,给一个叫做 var 的变量赋值Hello world! (在命令行里输入 set var=Hello world! )。然后我们的打算把变量 var 里的值赋给另一个变量 var1 ,做法是:set var1=%var% ,此时 var1 里的值也是 Hello world! 了。假如不使用百分号 % 仅仅是 set var1=var 的话,那么此时变量 var1 所得到的值仅仅是 var 这3个字母而已。再回顾一下 echo 的用法,分别尝试输入 echo var1 和 echo %var1% ,所得到的返回输出分别为:var1 和 Hello world! 。

此外,百分号可以对变量中的字符串有效地进行编辑或变换。
值得一提的是替换功能,其格式为:原始变量的名称后面跟上冒号 : ,再加上想要被代替的内容,紧接着一个等号 = ,然后再加上用来代替的新内容,最后用两个百分号把以上这些包括起来即可。虽然此时原始变量的值并没有改变,但百分号里的内容可以赋给一个变量,这个变量可以是原始变量。例:echo %var:o=z% ,效果为把 Hello world! 里所有的字母 o 都用字母 z 代替,并显示出来,然而变量 var 的值却没有变化。
当然,我们并不会满足于仅仅是代替一个字母——有时候我们需要代替两个。set var2=%var:ld=ms and bugs% ,这条命令可以在把 Hello world! 里的 ld 替换成 ms and bugs 并将新的结果赋给变量 var2 ,变量 var 仍然不会变化。输入 echo %var2% 确认一下结果是否为我们所期待的 Hello worms and bugs! 。

对变量中的字符串在特定位置上的删减将用到这样的格式:%var:~m% 和 %var:~m,n% 。m 和 n 为整数参数。数字 m 为正数表示取变量 var 中从左侧数第 m 个字符(单字节字符)以后的内容;m 为负数则表示取变量 var 从右侧数第 -m 个字符以及其右侧的所有的字符,这就是第一条命令所产生的新字符串。如果数字 n 为正数,表示在上述新字符串中,从其左侧取 n 个字符的内容;若 n 为负数,则从其左侧取字符直到还剩下 -n 个字符为止的内容。

如果您坚持认为这种抽象的表达方式是根本无法解释清楚这该死的 m 和无耻的 n 究竟是怎么回事的话,不如实验一下下面的例子。为了方便查看效果,我们假定变量 var 中的内容为 1234567890 (set var=1234567890),然后依次输入以下命令并查看相应的结果。
输入的命令    结果    效果                   
echo %var%    1234567890 显示所有                 
echo %var:~4%   567890   从第4个字符以后开始显示         
echo %var:~4,3%  567     从第4个字符以后开始显示,并只显示前3个  
echo %var:~-4%  7890    从倒数第4个字符开始显示         
echo %var:~-4,3% 789     从倒数第4个字符开始显示,并只显示前3个  
echo %var:~4,-2% 5678    从第4个字符以后开始显示,显示到还剩2个为止
echo %var:~0,3%  123     从头开始显示,并只显示前3个字符     
echo %var:~0,-3% 1234567   从头开始显示,显示到还剩3个字符为止   

此外,set 也可以对数值型的变量进行常见的运算操作。
set /a num=48
set /a result=%num%+12
echo %result%
上面的命令表示先给数值 48 赋给变量 num ,然后再把变量 num 的数值与数值 12 相加后的结果赋给变量 result 。第3行可以显示变量 result 的值,结果很明显,是 60 。

3.2 调用

与很多编程类的东西一样,批处理并不一定非得按照文本中命令的排列顺序一行一行地执行。如果遇到了 goto、call、start 这样的跳转、调用、启动等语句,程序通常会变得多层化,执行起来会更加有效。

3.2.1 跳转

goto 对于多少有点编程基础的朋友来说,想必不是一件难以理解的东西。goto 跟上标签就能直接让程序从该标签处开始继续执行随后的命令,不论标签的位置是在该 goto 命令的前面还是后面。标签必须以单个冒号 : 开头,但不区分大小写。有个特殊的标签 :EOF 或 :eof 能将控制转移到当前批脚本文件的结尾处,它是不需要事先定义的。
::::::::::::跳转.bat::::::::::::
@echo off
goto :FirstLable

:SecondLable
echo 然后显示这句
pause
goto :EOF

:FirstLable
echo 首先显示这句
pause
goto :SecondLable
::::::::::::::::::::::::::::::::

3.2.2 调用

call 主要体现在两个方面:一是调用该批处理以外的另一个批处理(事实上调用该批处理本身也可以,只是可能会带来不必要的死循环);另一方面是有着与 goto 类似的向特定标签处跳转的功能。然而,call 的独特之处在于:在调用的批处理或标签后的内容处理完成以后,控制会继续执行 call 后面的语句。我们先来看一下用 call 进行跳转的效果。为了方便对比,我们将上面的批处理作如下修改(浅色文字为修改部分)。
::::::::::::跳转.bat::::::::::::
@echo off
call :FirstLable

:SecondLable
echo 然后显示这句
pause
goto :EOF

:FirstLable
echo 首先显示这句
pause
::goto :SecondLable
::::::::::::::::::::::::::::::::
在用 call 跳转到 :FirstLabel 处执行到程序结尾后(此时 call 的任务才刚刚完成),会继续回到 call 语句后的 :SecondLabel 处。假如 goto :SecondLabel 这一句没有被注释掉的话,那么控制会跳转到 :SecondLabel 处直到 goto :EOF 处 call 的使命才真正完成。而且,call 在完成任务后,下面的 :SecondLabel 处内容会再次执行一遍。

当 call 作为调用其他新的批处理的用途时,当前批处理就会暂停,直到新的批处理结束后,之前的批处理才会继续执行。例如:直接调用当前路径里的一个批处理 call test.bat ,或是要调用的批处理在当前路径向上一级的abc文件夹里 call ..\abc\test.bat ,也可以使用绝对路径找到目标批处理 call D:\abc\test.bat (路径的写法请参阅[前言]里命令 cd 的用法介绍)。当然,一个最直观的例子往往更能说明问题。建立两个批处理(假设他们在同一路径下)"调用.bat"和"被调用.bat",它们的内容分别为:
::::::::::::调用.bat::::::::::::
@echo off
echo 这里是 调用.bat
pause

call 被调用.bat

echo 现在又回到了 调用.bat
pause
::::::::::::::::::::::::::::::::

:::::::::::被调用.bat:::::::::::
echo 这里是 被调用.bat
pause
::::::::::::::::::::::::::::::::
编辑并保存好这两个批处理,然后运行批处理"调用.bat",所得到的结果跟我们预期的完全一致。

3.2.3 启动

start 虽然也不是一个简单的命令,但用法绝对不难理解。来几个例子:start msconfig 用来打开"系统配置应用程序";start notepad 则可以打开一个记事本;start "这就是所谓的标题" cmd 用来打开一个新的命令提示符;start "随便写个标题" http://www.baidu.com 便打开百度的首页;而 start "开玩了" E:\game\starcraft\starcraft.exe 却是开始星际争霸(如果您的电脑里安装了星际且路径与上述一致的话)等等。虽然 start 的参数很多(具体用法在输入 help start 后可以得到),但通常情况下我们只需要知道 start 后面加上标题,再跟上想要执行程序、命令或网址即可。值得注意的是:标题要用双引号引用起来,否则会被作为可执行的文件来处理;所要执行的东西如果不是系统内部程序或命令的话,则需要我们给出具体的路径,比如绝对路径。
当然,start 也可以打开另外一个批处理。这看起来似乎与 call 相仿,却有一些区别。为了对比 call 和 start 之间的效果差异,可以在上一个例子中修改"调用.bat"中的 call 被调用.bat 为 start 被调用.bat 。从"调用.bat"开始执行后,"被调用.bat"也的确能够被调用。但之前的批处理也同时继续执行着。事实上,此时这两个程序已经完全独立开了,是两个独立的进程。

3.3 参数

上文提到了调用,这里就不得不补充一下参数。何谓参数?假如您要使用命令 dir ,那后面所跟的路径文件名也好、/p (分页显示)也好、/w (宽列表显示)也好、又或者是 /s (所有目录及子目录)也好,这些都能被称作为参数。对于一条命令来说,它除了能返回(输出)给我们一些信息以外,我们还经常给它输入一些信息,被输入的信息就是参数;然而,对于一个批处理来说,它除了能为我们工作(输出结果)以外,有时也需要外界给他一些信息。

3.3.1 参数的传递

为了很好的认识到这一点,我们先稍微修改一下上文所使用的"被调用.bat"这个批处理文件,使之能够接受处理外界给它的输入参数。
:::::::::::被调用.bat:::::::::::
echo 这里是 被调用.bat
echo 您输入的第1条参数为 %1
echo 您输入的第2条参数为 %2
pause
::::::::::::::::::::::::::::::::
其中,%1 和 %2 分别代表运行"被调用.bat"批处理时所跟的两个参数。那么它该如何获得所谓的参数1和参数2呢。双击运行"被调用.bat"当然是不行的了。可以在命令提示符里输入"被调用.bat"的全名,并在后面加上两个参数即可(如果"被调用.bat"不在当前工作路径,需要输入"被调用.bat"的路径,比如绝对路径,以便让计算机找到它)。就像:D:\批处理\test\被调用.bat Tom and Jerry 。运行时我们会发现 %1 和 %2 分别显示为 Tom 和 and ,Jerry 为作为第3个参数来处理,但该批处理中却未用到 %3 。提示:在XP等操作系统中,对于汉字的输入可用 Ctrl + 空格 切换出中文输入法;也可以按 Tab 键让其自动切换并补充完成您所想要输入的路径。

为了进一步验证这一点,我们再改一下批处理"调用.bat",让它在调用其他批处理时加上参数
::::::::::::调用.bat::::::::::::
@echo off
echo 这里是 调用.bat
pause

call 被调用.bat Hello world!

echo 现在又回到了 调用.bat
pause
::::::::::::::::::::::::::::::::

3.3.2 参数的输入与输出

参数不仅可以是值,也可以是变量。如果是变量的话,它既可以作为输入,也可以作为输出。为此,我们需要分别再改一次"调用.bat"和"被调用.bat"。

::::::::::::调用.bat::::::::::::
@echo off
echo 这里是 调用.bat
pause

set /p Num=请输入一个整数:
set Square=

call 被调用.bat Num Square

echo 现在又回到了 调用.bat ,而且,%Num% 的平方是 %Square% 。
pause
::::::::::::::::::::::::::::::::

:::::::::::被调用.bat:::::::::::
echo 这里是 被调用.bat
echo 您输入的第1条参数为 %1
echo 您输入的第2条参数为 %2

set /a %2 = %1 * %1

echo 经过计算后,您输入的第1条参数为 %1
echo 经过计算后,您输入的第2条参数为 %2
pause
::::::::::::::::::::::::::::::::

可以看出,在批处理"被调用.bat"中的 call 被调用.bat Num Square 里,变量 Num 和 Square 被传递过去的只是变量名而已,而不是变量中的数值。另外,尝试将"调用.bat"中的 call 被调用.bat Num Square 换为 call 被调用.bat %Num% Square ,然后再对比一下结果,相信您一定会有所收获。

3.3.3 函数

在一个批处理的内部调用时,使用参数会怎么样呢?那么这就是函数的雏形。把之前的"跳转.bat"稍微也改一下
::::::::::::跳转.bat::::::::::::
@echo off
call :FirstLable 很好很强大

:SecondLable
echo 然后显示这句
pause
goto :EOF

:FirstLable
echo 首先显示这句,后面跟的参数为 %1
pause
::::::::::::::::::::::::::::::::

对于 goto 所跟的标签或 start 所跟的程序,它们后面能否加参数呢?答案是:前者是否定的;后者是肯定的,试试看。

3.4 后记

写了那么多天,也许我们应该来点更实际更有用的东西。前几天无意中发现了一个163邮箱登录器,在此作为例子介绍一下。

:::::::163邮箱登录器.bat::::::::
@echo off
::不显示命令行
mode con cols=32 lines=8
::设置窗口的尺寸
title 163邮箱登录器
::设置该批处理的标题
color 3a
::设置背景(暗靛色)和文字(亮绿色)的颜色。
::另外,在命令提示符中输入 color/? 可获得详细的颜色信息

set /p username=帐号:
set /p password=密码:
::给出输入的提示,并将字符串赋给相应的变量

start "正在登录邮箱" "https://reg.163.com/logins.jsp?username=%username%&password=%password%&url=http://fm163.163.com/coremail/fcg/ntesdoor2"
::事实上,那个网址链接才是整个程序的核心部分,注意其中的 %username% 和 %password% 分别是指变量 username 和 password 里的字符串内容。
::::::::::::::::::::::::::::::::

Collected by Clove--Mail to Me

Windows 批处理脚本学习教程