上一篇文章分享了Bat批处理的部分基础知识,包括echo、@、pause命令、批处理注释、重定向符号、批处理文件参数,今天继续分享Bat批处理的基础知识set命令和延迟环境变量扩展。
1. set命令
set 命令用来显示、设置或删除 cmd.exe 环境变量,set 命令在编写批处理脚本时使用频率非常高,语法如下:
SET [variable=[string]]
参数说明:
variable 指定环境变量名。
string 指定要指派给变量的一系列字符串。
显示当前环境变量,键入不带参数的 SET。实例:
上图显示了path和tmp环境变量的值,即下图电脑上设置的环境变量;
set后面还可以只跟一个字母,即可列出以这个字母开头的变量名和值;
如果在当前环境中找不到该变量名称,SET 命令将把 ERRORLEVEL设置成 1,如下实例:
@echo off
set tmp
echo errorlevel=%errorlevel%
set java
echo errorlevel=%errorlevel%
pause
在使用set进行赋值时,有几个注意事项:
①等号两边不要有空格。
②变量值包含特殊字符需用双引号。
③避免使用系统环境变量同名的自定义变量。
2.SET扩展命令 /A 和 /P
/A 命令
/A 命令行开关指定等号右边的字符串为被评估的数字表达式。该表达式解析很简单并以递减的优先权顺序支持下列操作:
/A参数就是让SET可以支持数学符号进行加减等一些数学运算。
在使用任何逻辑或取余操作符时, 需要将表达式字符串用引号扩起来,在表达式中的任何非数字字符串键作为环境变量名称,这些环境变量名称的值已在使用前转换成数字。
实例:
@echo off
::使用 /A 执行加法运算,val=15。
set /A val=6+9
echo %val%
::将 val 环境变量加6,赋值给val2环境变量,val=25。
set /A val2=%val%+10
echo %val2%
::将 11 使用位移操作符,向右移动一位,移动一位等于除以2,val=5。
set /A "val3=13>>1"
echo %val3%
::使用分组符号提升加法的优先级,val=30。
set /A val4=(0+1+2+3+4+5+6+7+8+9)/3*2
echo %val4%
::使用 %% 进行取余运算,val=2。
set /A "val5=82%%10"
echo %val5%
pause
运行结果:
如果指定了一个环境变量名称,但未在当前环境中定义,那么值将被定为零,可以使用环境变量值做计算而不用键入那些 % 符号来得到它们的值。如下实例:
@echo off
::下面在 set 中使用A 参与运算,但是 tmp 并没有定义
::默认 A 为 0,因此 val=22
set /A val=A+22
echo %val%
::下面在 set 中使用 %B% 获取变量 B 的值,B=11,
::因此val2=33
set B=11
set /A val2=%B%+22
echo %val2%
pause
运行结果:
/P 命令
/P 命令行开关允许将变量数值设成用户输入的一行输入。读取输入行之前,显示指定的 promptString。promptString 可以是空的。语法:
set /P variateName=promptStrig
说明:variateName 为变量名
promptStrig 为提示字符串,将在 DOS 窗口中显示
实例:
@echo off
::提示用户输入姓名,username为变量名,“请输入姓名”为提示信息。
set /p username=请输入姓名:
echo 你的姓名:%username%
pause
运行结果:
变量替换
%变量名称:变量1=变量2%
用“变量2”替代结果中的每一个“变量1”。实例:
@echo off
set val=hello world! it's good world!
echo %val%
::将val值中的所有world替换成man
echo %val:world=man%
pause
运行结果:
%变量名称:变量1=变量2%,当“变量2”为空时,可以删除所有“变量1”。实例:
@echo off
set val=hello world! it's good world!
echo %val%
::将val值中的所有l替换成空值
echo %val:l=%
pause
运行结果:
%变量名称:变量1=变量2%,当“变量2”前面加符号 * 时,可以替换“变量1”中第一次出现“变量2”之前的所有字符。实例:
@echo off
set val=hello world! it's good world!
echo %val%
::将val值中的第一个l之前的所有字符替换成AA
echo %val:*l=AA%
pause
运行结果:
子字符串
%变量名:~10,6%只使用变量中从第 11 个(偏移量 10)字符开始的6个字符;如果没有指定长度,则显示剩余所有字符;如果偏移量和长度都是负数,使用的数字则是环境变量数值长度加上指定的偏移量或长度。
实例:
@echo off
set val=hello world! it's good world!
echo %val%
::截取val值中第6个字符开始的后面3个字符
echo %val:~6,3%
::如果没有指定长度,则采用默认值,即显示变量值剩下的所有字符。
echo %val:~6%
::提取 val 变量的最后6个字符
echo %val:~-6%
::从倒数第6个字符开始,提取3个字符
echo %val:~-6,3%
::提取 val 变量的所有字符,除了最后两个
echo %val:~0,-3%
::提取倒数第6个字符开始到结尾的字符,除了最后3个字符
echo %val:~-6,-3%
pause
运行结果:
3.延迟环境变量扩展
在CMD命令窗口中:
/V:ON 启用延迟环境变量扩展,变量名使用 ! 作为分隔符。
/V:OFF 禁用延迟的环境扩展。如下图,在没有开启延迟环境变量扩展时,echo !val!是原样输出变量名,并没有输出变量值,通过/V:NO开启延迟环境变量扩展后,echo !val!输出了变量值。
为了理解什么是延迟环境变量扩展,我们先来看一下什么是变量扩展;在CMD在解释命令的时候,会先读取命令行一条完整的命令,然后对其进行一些命令格式的匹配操作,核对一下所输入的命令格式是不是符合他的要求,在变量名字两边加一个%号,如%name%,当CMD在对读取整行命令进行格式匹配时,发现name这个字符两边加了%号,就不会把它当作普通字符处理,而是会把它当作一个变量处理,变量名叫name;然后CMD就会找到变量名对应的值,用变量名的值替换掉这个变量名字(name),如果变量名不存在值,就返回空值,再将这个替换好并且匹配的命令执行,这个替换值的过程,就叫变量扩展;说白了就是把变量的名字,用它的值给替换掉后执行,也就是批处理如何识别一个变量的过程。变量扩展的例子:
@echo off
set AA=123
set var=%AA%
echo %var%
pause
运行结果:
CMD在读取到echo %var%这条命令后,就会进行匹配操作,它发现var字符两边有%号,这时就会%var%当作一个变量处理,查看这个var变量名是不是有值,如果有就用var的值把变量名var给替换掉,echo %var%的上一条命令set var=%AA%中,给var赋值为%AA%,所以会用AA变量把%var%这个变量名替换掉,替换后的结果为echo %AA%,匹配完后,再执行echo %AA%这条语句,这时它会发现AA也是一个变量,就会继续向上找,把123替换过来,这时CMD中就会echo出一个123了。
那为什么要用延迟环境变量扩展呢?
CMD在解释命令时,会先把一条完整的命令进行读取,然后进行匹配操作,匹配时它会把命令里的变量用变量的值替换掉,然后执行这个替换好的命令。在Bat批处理脚本中,IF FOR这样的命令都可以加括号,将一些命令嵌套在里面执行,这样的话对于一条可以加扩号嵌套其它命令的命令,它的完整格式就是for %%i in (…)这样一个整体,如果我们在括号里面嵌入一些设置变量值的命令,就会出现问题了。看下面的例子:
@echo off
for /l %%i in (1,2,6)
do (
set var=%%i
echo %var%)
pause
运行结果:
上面的代码整个作为一个完整的命令来处理,当作一个整体,读取到内存中,然后进行预处理,此时的 set var=%%i 并不是做赋值处理 而是当作字符放入批处理,所以echo的时候 var 其实还是空值,打印的时候会报错。在命令中加入一条:setloacl ENABLEDELAYEDEXPANSION 启用延迟环境变量扩展,打印的时候就不会报错了。注意:启用延迟环境变量扩展后,变量名要用!分隔。
@echo off
::启用延迟环境变量扩展
setlocal ENABLEDELAYEDEXPANSION
for /l %%i in (1,2,6)
do (
set var=%%i
echo !var!)
pause
运行结果:
延迟变量全称"延迟环境变量扩展", 是为了解决在for语句这类嵌套命令的命令中无法设置变量值的问题以及通过连接符执行的命令的问题。通过连接符执行的命令的例子:
@echo off
::此时整句作为预处理加载到内存,var并没有被赋值,还是个空值
set var=AA & echo %var%
pause
运行结果:
开启延迟环境变量扩展(%var%要换成!var!):
@echo off
::开启延迟环境变量扩展
setlocal ENABLEDELAYEDEXPANSION
set var=AA & echo !var!
pause
运行结果: