本帖最后由 Hello123World 于 2011-12-22 17:35 编辑
【原】[一日一教学]批处理系列帖子索引 http://bbs.bathome.net/thread-2576-1-1.html
【续】[一日一教学]批处理系列帖子索引 http://bbs.bathome.net/thread-13798-1-1.html
帮助信息: | 显示、设置或删除 cmd.exe 环境变量。 | | | | SET [variable=[string]] | | | | variable 指定环境变量名。 | | string 指定要指派给变量的一系列字符串。 | | | | 要显示当前环境变量,键入不带参数的 SET。 | | | | 如果命令扩展被启用,SET 会如下改变: | | | | 可仅用一个变量激活 SET 命令,等号或值不显示所有前缀匹配 | | SET 命令已使用的名称的所有变量的值。例如: | | | | SET P | | | | 会显示所有以字母 P 打头的变量 | | | | 如果在当前环境中找不到该变量名称,SET 命令将把 ERRORLEVEL | | 设置成 1。 | | | | SET 命令不允许变量名含有等号。 | | | | 在 SET 命令中添加了两个新命令行开关: | | | | SET /A expression | | SET /P variable=[promptString] | | | | /A 命令行开关指定等号右边的字符串为被评估的数字表达式。该表达式 | | 评估器很简单并以递减的优先权顺序支持下列操作: | | | | () - 分组 | | ! ~ - - 一元运算符 | | * / % - 算数运算符 | | + - - 算数运算符 | | << >> - 逻辑移位 | | - 按位“与” | | ^ - 按位“异” | | | - 按位“或” | | = *= /= %= += -= - 赋值 | | &= ^= |= <<= >>= | | , - 表达式分隔符 | | | | 如果您使用任何逻辑或取余操作符, 您需要将表达式字符串用 | | 引号扩起来。在表达式中的任何非数字字符串键作为环境变量 | | 名称,这些环境变量名称的值已在使用前转换成数字。如果指定 | | 了一个环境变量名称,但未在当前环境中定义,那么值将被定为 | | 零。这使您可以使用环境变量值做计算而不用键入那些 % 符号 | | 来得到它们的值。如果 SET /A 在命令脚本外的命令行执行的, | | 那么它显示该表达式的最后值。该分配的操作符在分配的操作符 | | 左边需要一个环境变量名称。除十六进制有 0x 前缀,八进制 | | 有 0 前缀的,数字值为十进位数字。因此,0x12 与 18 和 022 | | 相同。请注意八进制公式可能很容易搞混: 08 和 09 是无效的数字, | | 因为 8 和 9 不是有效的八进制位数。(& ) | | | | /P 命令行开关允许将变量数值设成用户输入的一行输入。读取输入 | | 行之前,显示指定的 promptString。promptString 可以是空的。 | | | | 环境变量替换已如下增强: | | | | %PATH:str1=str2% | | | | 会扩展 PATH 环境变量,用 "str2" 代替扩展结果中的每个 "str1"。 | | 要有效地从扩展结果中删除所有的 "str1","str2" 可以是空的。 | | "str1" 可以以星号打头;在这种情况下,"str1" 会从扩展结果的 | | 开始到 str1 剩余部分第一次出现的地方,都一直保持相配。 | | | | 也可以为扩展名指定子字符串。 | | | | %PATH:~10,5% | | | | 会扩展 PATH 环境变量,然后只使用在扩展结果中从第 11 个(偏 | | 移量 10)字符开始的五个字符。如果没有指定长度,则采用默认 | | 值,即变量数值的余数。如果两个数字(偏移量和长度)都是负数, | | 使用的数字则是环境变量数值长度加上指定的偏移量或长度。 | | | | %PATH:~-10% | | | | 会提取 PATH 变量的最后十个字符。 | | | | %PATH:~0,-2% | | | | 会提取 PATH 变量的所有字符,除了最后两个。 | | | | 终于添加了延迟环境变量扩充的支持。该支持总是按默认值被 | | 停用,但也可以通过 CMD.EXE 的 /V 命令行开关而被启用/停用。 | | 请参阅 CMD /? | | | | 考虑到读取一行文本时所遇到的目前扩充的限制时,延迟环境 | | 变量扩充是很有用的,而不是执行的时候。以下例子说明直接 | | 变量扩充的问题: | | | | set VAR=before | | if "%VAR%" == "before" ( | | set VAR=after | | if "%VAR%" == "after" @echo If you see this, it worked | | ) | | | | 不会显示消息,因为在读到第一个 IF 语句时,BOTH IF 语句中 | | 的 %VAR% 会被代替;原因是: 它包含 IF 的文体,IF 是一个 | | 复合语句。所以,复合语句中的 IF 实际上是在比较 "before" 和 | | "after",这两者永远不会相等。同样,以下这个例子也不会达到 | | 预期效果: | | | | set LIST= | | for %i in (*) do set LIST=%LIST% %i | | echo %LIST% | | | | 原因是,它不会在目前的目录中建立一个文件列表,而只是将 | | LIST 变量设成找到的最后一个文件。这也是因为 %LIST% 在 | | FOR 语句被读取时,只被扩充了一次;而且,那时的 LIST 变量 | | 是空的。因此,我们真正执行的 FOR 循环是: | | | | for %i in (*) do set LIST= %i | | | | 这个循环继续将 LIST 设成找到的最后一个文件。 | | | | 延迟环境变量扩充允许您使用一个不同的字符(惊叹号)在执行 | | 时间扩充环境变量。如果延迟的变量扩充被启用,可以将上面 | | 例子写成以下所示,以达到预期效果: | | | | set VAR=before | | if "%VAR%" == "before" ( | | set VAR=after | | if "!VAR!" == "after" @echo If you see this, it worked | | ) | | | | set LIST= | | for %i in (*) do set LIST=!LIST! %i | | echo %LIST% | | | | 如果命令扩展被启用,有几个动态环境变量可以被扩展,但 | | 不会出现在 SET 显示的变量列表中。每次变量数值被扩展时, | | 这些变量数值都会被动态计算。如果用户用这些名称中任何 | | 一个定义变量,那个定义会替代下面描述的动态定义: | | | | %CD% - 扩展到当前目录字符串。 | | | | %DATE% - 用跟 DATE 命令同样的格式扩展到当前日期。 | | | | %TIME% - 用跟 TIME 命令同样的格式扩展到当前时间。 | | | | %RANDOM% - 扩展到 0 和 32767 之间的任意十进制数字。 | | | | %ERRORLEVEL% - 扩展到当前 ERRORLEVEL 数值。 | | | | %CMDEXTVERSION% - 扩展到当前命令处理器扩展版本号。 | | | | %CMDCMDLINE% - 扩展到调用命令处理器的原始命令行。COPY |
.
命令概括:
set,意为“设置”。
variable,意为“变量”;
/a,arithmetic,意为“算术”(感谢demon的英文提供)。
/p,prompt,意为“提示”;
参数详解:
先从光杆的set命令说起。
1.显示当前所有环境变量
输入:setCOPY .
效果: | ALLUSERSPROFILE=C:\ProgramData | | APPDATA=C:\Users\helloworld\AppData\Roaming | | CommonProgramFiles=C:\Program Files\Common Files | | COMPUTERNAME=HELLOWORLD-PC | | ComSpec=C:\Windows\system32\cmd.exe | | FP_NO_HOST_CHECK=NO | | HOMEDRIVE=C: | | HOMEPATH=\Users\helloworld | | LOCALAPPDATA=C:\Users\helloworld\AppData\Local | | LOGONSERVER=\\HELLOWORLD-PC | | NUMBER_OF_PROCESSORS=2 | | OS=Windows_NT | | Path=C:\Program Files\Common Files\Microsoft Shared\Windows Live | | PATHEXT=.COM | | PROCESSOR_ARCHITECTURE=x86 | | PROCESSOR_IDENTIFIER=x86 Family 6 Model 15 Stepping 13, GenuineIntel | | PROCESSOR_LEVEL=6 | | PROCESSOR_REVISION=0f0d | | ProgramData=C:\ProgramData | | ProgramFiles=C:\Program Files | | PROMPT=$P$G | | PSModulePath=C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ | | PUBLIC=C:\Users\Public | | SESSIONNAME=Console | | SystemDrive=C: | | SystemRoot=C:\Windows | | TEMP=C:\Users\HELLOW~1\AppData\Local\Temp | | TMP=C:\Users\HELLOW~1\AppData\Local\Temp | | USERDOMAIN=helloworld-PC | | USERNAME=helloworld | | USERPROFILE=C:\Users\helloworld | | windir=C:\WindowsCOPY |
.
2.显示以指定字符串开头的环境变量
显示以“p”开头的环境变量。
代码:set pCOPY .
效果: | Path=C:\Program Files\Common Files\Microsoft Shared\Windows Live;C:\Windows\syst | | em32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v | | 1.0\;C:\Program Files\Common Files\Thunder Network\KanKan\Codecs;C:\Program File | | s\Windows Live\Shared | | PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC | | PROCESSOR_ARCHITECTURE=x86 | | PROCESSOR_IDENTIFIER=x86 Family 6 Model 15 Stepping 13, GenuineIntel | | PROCESSOR_LEVEL=6 | | PROCESSOR_REVISION=0f0d | | ProgramData=C:\ProgramData | | ProgramFiles=C:\Program Files | | PROMPT=$P$G | | PSModulePath=C:\Windows\system32\WindowsPowerShell\v1.0\Modules\ | | PUBLIC=C:\Users\PublicCOPY |
.
显示以“path”开头的环境变量。
代码:C:\Users\helloworld\Desktop>set pathCOPY .
效果: | Path=C:\Program Files\Common Files\Microsoft Shared\Windows Live;C:\Windows\syst | | em32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v | | 1.0\;C:\Program Files\Common Files\Thunder Network\KanKan\Codecs;C:\Program File | | s\Windows Live\Shared | | PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSCCOPY |
.
3.直接给变量赋值
变量有两个属性,一是变量名,二是变量值。
建议使用c语言的变量名命名规则:“只能由数字、下划线、字母构成,且不能以数字开头”!
批处理中变量名不能以数字开头,且变量名中不能含有“=”,其它可以随意(脚本的好处,也是脚本的坏处)。
代码: | @echo off | | Set a=hello world | | echo %a% | | pause>nulCOPY |
.
将字符串“hello world”赋值给变量a,并输出变量a的值。
“=”左边是变量名,“=”右边是变量的值。
4.等待用户输入变量值
这一节讲的就是/p参数的常规运用。
代码: | @echo off | | net start Schedule | | ::开启at服务 | | Set /p stime=请输入定时关机时间(例如:23:59): | | at %stime% shutdown /s /t 0 | | pauseCOPY |
.
这个代码的作用就是,等待用户输入一个时间,然后就会在指定时间关机。
前面说过“=”右边的是变量值,但是这里却不是变量值,而是提示信息,用户输入的字符串才是变量值,因为在set 中加了 /p参数!
5.set的计算功能
set的计算功能可以说是set中最繁杂的一种功能,但你不能不承认——它确实很强大。
①.怎么进行加减乘除?
代码: | @echo off | | ::加 | | Set /a n1=1+1 | | ::减 | | Set /a n2=2-1 | | ::乘 | | Set /a n3=2*3 | | ::除 | | Set /a n4=8/2 | | echo 和:%n1%,差:%n2%,积:%n3%,商:%n4% | | pause>nulCOPY |
.
可以看出,不论进行哪一种算术运算都含有/a参数,其实不仅仅是算术运算,所有的运算都离不开/a参数。
②.怎么求余数(取模)?
批处理中有一项专门用来求余数的运算符“%”。
在命令行下: | C:\Users\helloworld\Desktop>set /a 9%4 | | 1COPY |
.
在批处理文件中: | @echo off | | Set /a n=9%%4 | | echo %n% | | pause>nulCOPY |
.
可能有人会问:“为什么一个运算符,在命令行和批处理文件中会出现不同的写法呢”,其实写法还是没有变的,都是“%”,只不过%符号比较特殊,在批处理中要先进行一次转义(而%又只能用%转义),看到这里可能你还是不明白,这里可以做一个实验——实验要求:输出一个%。
在命令行下: | C:\Users\helloworld\Desktop>echo % | | %COPY |
.
在批处理文件中: | @echo off | | echo %% | | pause>nulCOPY |
.
③.复合算术运算符
复合运算符一共有10个,其中复合算术运算符有5个,它们分别是“+=,-=,*=,/=,%=”。
复合运算符只要使用得当,可以很好的节省代码量。
先看一个例子:
计算1-100这100个数字的和。 | @echo off | | Set n=0 | | for /l %%i in (1 1 100) do Set /a n=n+%%i | | echo %n% | | pause>nulCOPY |
.
这个代码中Set /a n=n+%%i,第二个n的两边没有“%”,按照常规,变量在引用时,要在变量名两边加上“%”——set /a的特性就是在引用变量时,可以省略 “%”(当然你也可以不省略——但强烈建议你省略)。
用复合算术运算符简写: | @echo off | | Set n=0 | | for /l %%i in (1 1 100) do Set /a n+=%%i | | echo %n% | | pause>nulCOPY |
.
对比两个代码,唯一的差别就是 n=n+%%i 与 n+=%%i。
难道n+=%%i就是 n=n+%%i的意思?
事实上也是如此,而且5个复合算术运算符都是这种意思。
“变量1 复合运算符 变量2” 就等于“变量1=变量1 对应的算术运算符 变量2”。
例如:
n*=3 就是 n=n*3。
建议新手跳过第④小节的讲解,免得转的头晕。
④.位运算符
前面讲解的运算符都是对于字节的运算,但是位运算符却是对于更小的单位——位,进行运算(1字节=8位)。
进行位运算符的学习,需要对2进制有所了解,懂得简单的 10进制 to 2进制 的相互转换,而且要对原码、反码、补码的概念有所了解。
10进制=(8位)2进制补码:
9=0000 1001
5=0000 0101
-9=1111 0111
④.1.按位与运算符(&)
没错,它和and(echo hello & echo world)一摸一样,但是在此处它是按位与(Set /a 9^&5)。
这里,为了方便后面的教学,我们暂且将1称为真,0称为假。 | C:\Users\helloworld\Desktop>set /a 9^&5 | | 1 | | C:\Users\helloworld\Desktop>set /a -9^&5 | | 5COPY |
.
为什么写成^&?
跟前面的求余数运算符是一样的道理,由于&符比较特殊,所以需要转义(%必须由%转义,&必须要^转义)。
9和5、-9和5按位与的结果分别为1,5,Why?
位运算就是要用10进制数对应的二进制补码进行运算,然后再将运算得到的二进制补码换算成10进制数输出(这是计算机本身特性决定的,不知道你还记不记的大明湖畔的夏雨荷——计算机科学的基础就是:0,1)。
9: 0000 1001
&
5: 0000 0101
---------------------
1: 0000 0001
-9:1111 0111
&
+5:0000 0101
---------------------
+5:0000 0101
按位与运算,就是“同真为真,其余为假”,在同一位上都是1运算结果才是1,其余都是0.
④.2.按位或运算符(|)
“|”符号在set /a 之外还有“管道”的用法,但是在set /a 中它只是按位或(由于|符号的特殊性,在运用时也要在前面加转义符——^|)。
. | C:\Users\helloworld>set /a 5^|9 | | 13 | | C:\Users\helloworld>set /a 5^|-9 | | -9COPY |
.
9: 0000 1001
|
5: 0000 0101
---------------------
13: 0000 1101
-9:1111 0111
&
+5:0000 0101
---------------------
-9:1111 0111
按位或运算,就是“一真便真,全假才假”,同一位上只要一个是1,那结果就是1,只有全部是0,结果才是0.
结合前面的按位与(&)运算来看,其实按位与(&)和按位或(|)就是一种比较运算,比较同一位上的0或1的异同,得出结果。
④.3.逻辑移位
逻辑移位运算符有两个:<< ,>>,分别表示向左移位,向右移位。
向左移位(<<) | C:\Users\helloworld\Desktop>set /a 9^<^<2 | | 36COPY |
.
9: 0000 1001
<<
2
---------------------
36: 0010 0100
把二进制补码向左移动两位(不足的在右边补零),然后换算成10进制数得出结果(向左移是将数变大)。
计算公式:结果=被移数*(2的移位数次方)
例如:9<<2 == 9*(2的2次方) ==36
向右移位(>>) | C:\Users\helloworld\Desktop>set /a 9^>^>2 | | 2COPY |
.
9: 0000 1001
>>
2
---------------------
2: 0000 0010
把二进制补码向右移动两位(多余的剔除——这里剔除了最后一个1),然后换算成10进制数得出结果(向右移是将数变小)。
计算公式:结果=被移数/(2的移位数次方)
例如:9>>2 == 9/(2的2次方) == 2
逻辑移位运算符的特性可以加以利用,来计算数值的偶数倍、偶数半:
比如 9 的 2倍,即 Set /a 9^<^<1
比如 9 的 1/2,即 Set /a 9^>^>1
④.4.按位异或运算符(^)
按位异或运算符也是个特殊符号(转义符),所以在使用的时候也要转义(^^)。 | C:\Users\helloworld\Desktop>Set /a 9^^5 | | 12 | | C:\Users\helloworld\Desktop>Set /a -9^^5 | | -14COPY |
.
9: 0000 1001
^
5: 0000 0101
---------------------
12: 0000 1100
-9:1111 0111
^
+5:0000 0101
---------------------
-14:1111 0010
按位异或运算,就是“不同为真,相同为假”,相同位都是1或都是0,结果就是0,其余结果都是1.
④.5.复合位运算
结合前面的复合算术运算符和位运算符,复合位运算就不难理解。
例如:(&=)运算符 | @echo off | | Set n1=9 | | Set /a n1^&=5 | | echo %n1% | | pauseCOPY |
.
结果为1。
所以,“n1^&=5”就相当于“n1=n1^&5”(“&”需要转义)。
同理,“ n1^^=5”就相当于“n1=n1^^5”;"n1^|=5"就相当于“n1=n1^|5”
"n1^<^<=2"就相当于“n1=n1^<^<2”.
位运算就在这里结束了,其中“! ~ - ”这三个 “一元运算符”都没有讲解。
6.逗号运算符
如果两个变量的值都是数字,而不是字符串,就可以用set /a 中的逗号运算符一次性赋值。
例子: | @echo off | | Set /a a1=5,a2=5 | | echo %a1% %a2% | | pauseCOPY |
.
结果:5 5COPY .
如果变量值是字符串,用这种方法就会出错。
例如: | @echo off | | Set /a a1=5,a2=5a | | echo %a1% %a2% | | pauseCOPY |
.
结果: | 无效数字。数字常数只能是十进制(17),十六位进制(0x11)或 | | 八进制(021)。 | | 5COPY |
.
只输出了a1的值,a2没有输出,因为a2的值是字符串。
看起来像字符串的16进制数。
例如: | @echo off | | Set /a a1=5,a2=0x15 | | echo %a1% %a2% | | pauseCOPY |
.
结果:5 21COPY .
“0x15”中0x是16进制数前缀(等于10进制数21)。
"015"中0是8进制数前缀(等于10进制数13)。
7.替换变量中的字符串
①.将变量中指定字符串替换成其它字符串
例如:
将字符串中的“o”替换为“-”。 | @echo off | | Set str=helloworld | | Set str=%str:o=-% | | echo %str% | | pauseCOPY |
.
结果: | hell-w-rld | | 请按任意键继续. . .COPY |
.
②.异样替换,删除变量中的指定字符串
删除变量中的指定字符串其实就是将指定字符串替换为空值。
例如:
将字符串中的“o”删除。 | @echo off | | Set str=helloworld | | Set str=%str:o=% | | echo %str% | | pauseCOPY |
.
结果:
.
字符串替换还支持通配符“*”。
例如:
将第一个字符“o”前面的字符(包括“o”)全部删除。 | @echo off | | Set str=helloworld | | Set str=%str:*o=% | | echo %str% | | pauseCOPY |
.
结果:worldCOPY .
8.截取字符串
截取字符串就是将一个字符串中指定的部分提取出来。
例如,我要截取字符串“一二三四五六七八九十”中的“三四五”,有四种写法: | @echo off | | Set a=一二三四五六七八九十 | | Set a1=%a:~2,3% | | Set a2=%a:~2,-5% | | Set a3=%a:~-8,3% | | Set a4=%a:~-8,-5% | | echo %a1% %a2% %a3% %a4% | | pauseCOPY |
.
为什么这四种写法都能实现要求?
要解释会有很多种说法,我这里只能给出一句记忆口诀:
第一数,起始点。正左右,负右左。偏移!
第二数,结束点。正左右,负右左。终止!
解释第一句:“第一数,起始点。正左右,负右左。”就是“第一个数是起始点,如果是正数就从左往右数,如果是负数就从右往左数”。
以这一句为例,“Set a1=%a:~2,3%”
2是第一个数,而且是正数,所有从左往右数2个数:一二,“偏移!”就是移位。——起始点!
3是第二个数,也是正数,所有也从左往右数(从起始点开始数)3个数,三四五,“终止”!——终止点!
9.“输入光杆set,不会显示出来的”环境变量
%CD% - 扩展到当前目录字符串。
%DATE% - 用跟 DATE 命令同样的格式扩展到当前日期。
%TIME% - 用跟 TIME 命令同样的格式扩展到当前时间。
%RANDOM% - 扩展到 0 和 32767 之间的任意十进制数字。
%ERRORLEVEL% - 扩展到当前 ERRORLEVEL 数值。
%CMDEXTVERSION% - 扩展到当前命令处理器扩展版本号。
%CMDCMDLINE% - 扩展到调用命令处理器的原始命令行。
扩展阅读:
无 |