前言
在工作中偶尔会需要和bat脚本打交道,和linux系统的shell脚本相比,window系统的bat的脚本要少接触得多,而且二者的语法还存在比较大的差异,所以就整理一篇文章来记录一下对一些常见语法的使用和辨析吧
系列文章
一、变量的定义和使用
(一)变量的定义
定义变量十分简单,只需要使用set
关键字声明变量名和变量值即可,需要注意的是在bat
脚本中变量定义出来后默认都是字符串形式的,这点倒是和shell
脚本很像。如果变量值存在空格或者特殊字符的话,我们一般会用""
来将值进行包裹,比如"Hello World~"
注意:变量名和等号=
之间不能有空格!!!
set variable=xxxx
(二)变量的使用
我们可以通过%变量名%
的方式来取出变量值
案例演示
set a="Hello World~"
set b= "Hello My Girl~"
echo "a= %a%"
echo b= %b%
pause
我们可以看到,变量的值被正常打印出来了
结果如下
二、变量的输出:echo和@echo
(一)echo
echo
命令相信很多人都不陌生,我们常常利用这个命令来输出一些环境变量的值,格式如下:
echo %变量名%
案例演示
set a=bb
echo a=%a%
pause
从输出结果中我们可以看到,的确输出了a=bb
这段我们预想的字符串,不过同时我们也注意到命令本身也被输出到了cmd
窗口中。这是因为默认情况下,命令回显是打开的。
(二)@echo on
和@echo off
-
@echo on
:在批处理脚本中使用 @echo on 命令可以重新打开命令回显。当命令回显打开时,执行的命令将会显示在屏幕上。(默认情况下,脚本会处于@echo on
) -
@echo off
:在批处理脚本中使用 @echo off 命令可以关闭命令回显。当命令回显关闭时,执行的命令不会显示在屏幕上,只会显示命令的结果。这样可以提高脚本执行时的视觉清晰度,减少冗余输出。
案例演示
@echo off
set a=bb
echo a=%a%
@echo on
set a=cc
echo a=%a%
pause
从执行结果我们可以看出,使用了@echo off
之后命令确实没有再回显到cmd
窗口了
(三)@echo
一般情况下,@echo
和echo
的作用是一样的,都可以用来输出相关的文本或者变量。但如果是在@echo on
条件下,@echo
只会输出内容,而不会回显命令本身。
案例演示
@echo off
set a=aa
@echo on
echo a=%a%
@echo a=%a%
pause
我们从结果中可以看到,echo
会把执行的命令回显出来,而@echo
则不会。不过个人觉得这个也不算太大的差异,也就调试脚本的时候有用,最终的脚本正常来说都是统一配置@echo off
的。
三、代码暂停:pause
默认情况下,双击执行.bat
脚本后脚本执行结束就会马上关闭cmd窗口,期间如果报错cmd窗口也是一闪而过,无法看到错误信息。针对这种情况,我们可以在脚本的最后加上pause
命令。pause
用于在脚本执行过程中暂停并等待用户按下任意键继续执行。
我们常常利用这个命令来对写好的脚本进行调试。
案例演示
set a=bb
echo a=%a%
pause
echo a=%a%
pause
我们可以从执行结果中看到,因为加了两个pause
命令使得脚本停顿了2次。
四、脚本的注释 rem
和 ::
我们可以通过下面的小案例来演示一下:
set a=bb
:: set a=aa
set b=22
rem set b=11
echo a= %a%, b= %b%
pause
可以看到,rem
和 ::
后面的代码并没有被执行
PS:虽然网上说这两个语法存在差异,但在使用上暂时我是没有发现有什么不同
五、脚本的调用:call命令
在批处理脚本中,call 命令用于调用(执行)另一个批处理脚本或命令,并在执行完成后返回到当前脚本的位置。call 命令通常用于执行另一个脚本并传递参数,或者在执行完被调用脚本后继续执行当前脚本的后续命令。
语法格式:
call 脚本路径 [参数列表]
小案例
使用call命令执行dir
命令
call cd C:\Users\98093\Desktop\class\test
call dir /A
pause
执行结果
六、关于命令的帮助文档
有时候难免会遇到不熟悉的bat命令,或者是突然忘记了某个命令的参数名是什么,这个时候我们就可以通过查看命令的在线文档来快速查阅命令的使用方式
语法格式
命令名 /?
小案例
执行结果七、关于IF分支流程
(一)了解IF语法
和大多数语言的语法不同,bat语言的IF没有对条件进行包裹的,为了区别条件和执行语句,使用了括号()
来进行区分。语法格式如下:
IF 条件 (
命令1
) ELSE (
命令2
)
需要注意的点:
-
IF
、ELSE IF
、ELSE
这三个关键字和()
和条件中间需要有空格 - 对于字符串的比较,建议使用
""
将变量名和字符串进行包裹
案例演示
案例很简单,用来根据变量key
的值来输出不同的结果。
@echo off
set key=bb
if "%key%"=="aa" (
@echo "%key%==aa"
) else if "%key%"=="bb" (
@echo "key==bb"
) else (
@echo "key value unknown~"
)
pause
我们可以看到key
的值被正确比较了出来
(二)了解常用的条件表达式
需要注意的是,对于GTR
、LSS
等比较条件我们一般都是在比较数字的时候才会用到,使用的时候不区分大小写。同时,bat语法中不存在类似&&
和||
的写法来表示与和或。如果真有需要使用多个条件进行判断,一般来说解决方法是使用嵌套IF或者使用多个IF进行连接。
表达式 | 含义 |
---|---|
== | 等于 |
GTR | 大于 |
GEQ | 大于等于 |
LSS | 小于 |
LEQ | 小于等于 |
NOT | 非 |
案例演示
@echo off
set a=100
if %a% LSS 300 if %a% GTR 200 (
@echo a less then 300 and greater than 200
) else if %a% LEQ 200 if %a% GEQ 100 (
@echo a eqal or less then 300 and equal or greater than 200
) else (
@echo a less then 100
)
pause
我们可以看到,结果正常输出出来了
执行结果
八、关于标签(分支)定义和跳转:goto
bat脚本有个比较特别的分支跳转语法,支持我们在脚本中定义程序的走向。分支在一些稍微复杂的脚本中是比较常见的,可以让我们简化一些拥有共同处理方式的流程分支,在参数校验的时候用的比较多。
(一)标签(分支)的定义
语法格式
:分支名称
案例演示:
我们在下面定义了两个标签,需要注意的是即使在脚本中没有使用标签跳转,只要定义了标签,那么当代码执行到标签位置时就会把所有标签的代码都执行了!!!
:branch1
echo here is branch1
:branch2
echo here is branch2
(二)标签(分支)的跳转
语法格式
goto 分支名称
案例演示:(非最终版)
@echo off
set a=100
if %a% lss 300 if %a% gtr 200 (
goto branch1
) else if %a% leq 200 if %a% geq 100 (
goto branch2
) else (
goto branch3
)
:branch1
@echo a less then 300 and greater than 200
:branch2
@echo a eqal or less then 300 and equal or greater than 200
:branch3
@echo a less then 100
pause
从执行结果中,我们可以看出虽然代码成功跳转到对应的标签上面,但是却还把branch2
标签下面的branch3
代码块也执行了。这是因为如果没有显式地执行跳转到其他标签,脚本会按顺序执行,无论前面的条件是否满足。因此,执行完一个标签的内容后,会继续执行后续的标签内容。
(三)使用统一的标签作为最后的结束动作
从上一小节中我们知道,当前标签的代码执行完成后默认情况下会把剩余的所有标签代码都执行了,所以一般来说我们在标签中还会定义一个结束标签,用于普通标签执行结束后进行跳转。
基于这个理念,我们可以将上一小节的案例来进行优化
@echo off
set a=100
if %a% lss 300 if %a% gtr 200 (
goto branch1
) else if %a% leq 200 if %a% geq 100 (
goto branch2
) else (
goto branch3
)
:branch1
@echo a less then 300 and greater than 200
goto end
:branch2
@echo a eqal or less then 300 and equal or greater than 200
goto end
:branch3
@echo a less then 100
goto end
:end
pause
我们可以看到,现在代码就可以正常执行了,标签之间不会相互干扰
执行结果
(四)结合shift
实现for循环的效果
在一些比较复杂的脚本中,我们常常会利用标签跳转的特性和shift
命令来实现类似于for循环的效果。
先说说shift
命令
它的作用是将命令行参数向左移动一个位置。在 Batch
脚本中,通过使用 %1
、%2
、%3
等变量来访问命令行参数。当执行 shift
命令后,所有的命令行参数都会向左移动一个位置,原本的 %2
变为 %1
,%3
变为 %2
,以此类推。同时,原本的 %0
(脚本本身的名称)保持不变。
这个命令通常用于处理多个命令行参数或循环访问命令行参数的情况,特别是当不知道有多少个参数需要处理时。通过在循环中使用 shift 命令,可以逐个处理命令行参数,直到没有剩余参数为止。
案例演示
@echo off
:process_arguments
if "%1"=="" goto done
echo Processing argument: %1
shift
goto process_arguments
:done
echo All arguments processed.
pause
可以看到,每次打印完%1
之后我们会使用shift切换%1
以及后续参数的位置,然后重新回到标签的位置再重新输出%1
,从而实现参数迭代的效果,直到参数为空。
九、字符串的处理
(一)字符串的截取
语法格式
%variable:~start,length%
%variable% 是要截取的变量,start 是截取的起始位置(从 0 开始),length 是要截取的长度。
案例演示
@echo off
set a=123456789abcefg
set b=%a:~0,3%
set c=%a:~3,5%
set d=%a:~-3%
set e=%a:~-4,-2%
echo origin word is %a%
echo cut the first three characters, the result is %b%
echo cut the characters between 4 to 8, the result is %c%
echo cut the last three characters, the result is %d%
echo cut the characters between 4 to 2 from the bottom, the result is %e%
pause
我们可以看到,字符串可以根据我们的需要正序或者倒序地被截取
结果展示
(二)字符串的拼接
语法格式
set result=%str1%%str2%
result 是最终生成的字符串变量,str1
、str2
是需要拼接的字符串元素
案例演示
@echo off
set a=Hello
set b=World
set c=%a% %b%
echo the result is %c%
pause
结果展示
(三)字符串的替换
语法格式
%variable:search=replace%
%variable% 是要进行替换的变量,search 是要查找的内容,replace 是要替换的内容。
案例演示
@echo off
set a=11223344
set b=%a:22=33%
echo the source word is %a%
echo replace 22 to 33 ,the result is %b%
pause
结果展示
十、关于For循环的使用
(一)普通for循环
语法格式
这里有一点需要特别注意,我们正常来说使用一个变量是通过%variable%
来表达,但是在for循环中为了避免和正常的变量产生冲突,所以会把集合中的每个元素的定义格式统一用两个%%
来引用。
for %%variable in (set) do command
案例演示
@echo off
for %%i in (Today Is Wednesday) do (
echo %%i
)
pause
我们可以看到,我们顺利把字符串数组给打印了出来,需要注意的是bat
语法中没有数组定义的这一概念,导致我们很难通过提前定义数组的方式来替换掉in ()
里面的内容,个人觉得普通for循环是比较鸡肋的,效果很有限,我们一般比较少会用到这种用法。
(二)增强for循环,支持读取文件中的内容
我个人把for /f
这种写法成为增强for循环,因为这种语法要比普通for循环强大得多,不仅支持正常for循环的操作,还支持从文件中读取文本来进行循环操作,可以说是十分实用的命令了。
语法格式
如果存在多个options
,可以通过空格隔开
for /f "options" %%variable in (set) do command
支持的参数
eol=@ -指定一个行注释字符,遇到@开头的行就忽略掉。
skip=n - 指定在文件开始时忽略的行数。
delims=xx - 指定分隔符(可多个)。默认是空格和TAB。
tokens=x,y,m-n - 指定获取delims分割后的列内容
usebackq - 1.把单引号字符串作为命令;2.允许双引号扩起文件名称
案例演示
定义测试文件sorce.txt
1,man,Siri
2,man,Tom
3,woman,Sarry
4,woman,Kolora
定义脚本,如果不使用绝对路径的话,下面的脚本需要和测试文件放在同级目录下
@echo off
:: 定义文件位置,%~dp0表示当前目录。这里也可以通过指定绝对路径来实现
set filePath=%~dp0
set fileName=score.txt
:: 读取sorce.txt文件,将里面的名字输出出来
for /f "delims=, tokens=3" %%i in (%filePath%%fileName%) do (
echo the name is %%i
pause
结果展示
说在最后
个人觉得bat脚本不算太复杂,这是它的优点,也是它的缺点。简单意味着我们不需要用太高的成本就可以快速上手,但缺点也很明显,需求越复杂bat脚本就越捉襟见肘。所以个人觉得可以用bat脚本来做一些不复杂的工作来简化我们的操作,但不建议用它来开发复杂的功能和逻辑。
后续如果有其他值得一讲的语法,我也会继续更新在文章上面的
网友评论