• BAT 批处理 基础语法 教程 [MD]


    博文地址

    我的GitHub 我的博客 我的微信 我的邮箱
    baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

    目录

    BAT 批处理教程

    参考:易百教程
    参考:批处理之家

    当Windows为我们打开了五彩缤纷的图形窗口的时候
    DOS命中注定会陨落
    CMD毫无悬念将萎缩
    批处理逐渐趋向无声无息
    而powershell的到来,无疑会让更多的人忘记批处理
    这是一门即将失传的技艺
    这是一块行将就木的领域
    然而,命令行工具仍然具有批量处理一切的巨大威力
    字符界面仍然是高效操作、方便灵活、简洁快速的代名词

    基础语法

    特点

    • 批处理脚本存储在文本文件中,其中包含的命令按顺序依次执行,其功能是为了自动执行重复的命令序列
    • 批处理文件具有特殊的扩展名BAT或CMD,可以通过双击、或在命令提示符(cmd.exe)或在开始 - 运行行中运行
    • 批处理文件通过称为命令解释器的系统文件提供的接口(shell)来识别和执行,在Windows系统上是cmd.exe
    • 批处理文件可以读取用户的输入,有if、for等控制结构,支持函数、数组等高级功能,支持正则表达式,可以包含其他编程代码

    编码问题

    在windows上,bat文件默认以GBK编码格式保存(很多开发语言、环境的默认编码为UTF-8格式),如果文件中有中文或特殊符号,强烈建议以GBK编码格式保存,否则会因各种各样的问题导致乱码进而导致执行出错!

    如果不能修改文件编码格式,例如通过 for 等命令读写其他编码格式的文件,那需要使用CHCP修改编码格式。具体可用的编码参考 Code Page Identifiers

    @echo off & CHCP 65001
    :: 会在命令行中输出【Active code page: 65001】的提示
    

    注释

    注释有三种:

    • Rem 注释内容:Rem相当于命令,如果Rem的行数太多,可能会使代码变慢
    • :: 注释内容:建议采用这种方式的注释
    • %注释内容%:行内注释
    @echo off
    Rem Rem注释在未关闭命令回显时会在屏幕显示出来,而 :: 则什么情况下都不会显示
    echo 注释方式三 %行内注释%
    

    变量

    命令行参数

    可以在调用批处理文件时传递参数,%n(n为自然数)表示在调用批处理文件时传递的第n个参数:

    • %0 批处理文件本身,包括完整的路径和扩展名
    • %1 第一个参数
    • %9 第九个参数
    • %* 从第一个参数开始的所有参数

    参数%0具有特殊的功能,可以调用批处理自身,以达到批处理本身循环的目的,也可以复制文件自身等等。

    @echo off
    echo 第一个参数为:%1
    
    copy %0 d:
    ew_file.bat %最简单的复制文件自身的方法%
    

    set命令

    set [/A] varName=value
    :: 仅当该值是数值类型时,才可以使用【/A】,才能正确的进行数值计算,否则会被当做字符串进行计算
    :: 使用变量的时候,变量需要包含在%符号中,如【%varName%】
    
    set message=Hello World
    echo %message%
    
    SET /A a=5
    SET /A b=10
    SET /A c=%a% + %b%
    echo %c%
    

    局部与全局变量

    set globalvar=默认情况下都是全局变量
    
    SETLOCAL
    set var=SETLOCAL后定义的变量只在ENDLOCAL之前有效
    set globalvar=SETLOCAL后重新赋的值也只在ENDLOCAL之前有效
    echo %var%
    echo %globalvar%
    ENDLOCAL
    
    echo %var% %会打印:【ECHO 处于关闭状态。】%
    echo %globalvar%
    

    环境变量

    echo %JAVA_HOME%
    

    判断变量是否定义

    SET /A a=5
    SET str=包青天
    
    if defined a echo 【变量a存在】
    if not defined b echo 【变量b不存在】
    if not [%1]==[] echo 【参数存在:%1】
    if exist %1 echo 【文件 %1 存在】
    

    字符串

    基本操作

    set message=字符串
    echo 【%message%】
    
    set var=3
    set /A var=%var% + %var%
    echo 定义为字符串变量后,还可以使用【/A】开关转换为整数:%var%
    :: 上面打印内容为【6】,如果不加【/A】,那么打印结果为【3 + 3】
    
    :: 判断字符串是否相等
    if [%message%]==[字符串] echo 方式一
    if %message%==字符串 echo 方式二
    
    :: 创建一个空字符串
    Set a=
    if [%a%]==[] echo 检查是否为空字符串
    

    字符串截取

    其实和其他语言的规则是一致的,截取的标准格式为:

    %var:~num_chars_to_skip%
    %var:~num_chars_to_skip,num_chars_to_keep%
    即【%var:~fromIndex,length%】
    
    SET a=abcd
    
    echo 【%a:~0%】【%a:~1%】【%a:~2%】【%a:~3%】【%a:~4%】
    :: 【abcd】【bcd】【cd】【d】【】
    echo 【%a:~-4%】【%a:~-3%】【%a:~-2%】【%a:~-1%】
    :: 【abcd】【bcd】【cd】【d】-n和4-n的效果是一样的
    
    echo 【%a:~0,0%】【%a:~0,1%】【%a:~0,2%】【%a:~0,3%】【%a:~0,4%】
    :: 【】【a】【ab】【abc】【abcd】
    echo 【%a:~0,-4%】【%a:~0,-3%】【%a:~0,-2%】【%a:~0,-1%】
    :: 【】【a】【ab】【abc】【abcd】
    
    echo 【%a:~1,1%】【%a:~1,2%】【%a:~2,1%】【%a:~3,1%】【%a:~3,2%】
    :: 【b】【bc】【c】【d】【d】
    

    替换子字符串

    %str:new=old%
    
    set str=包青天 白  乾涛 包青天
    echo 【%str:包青=老%】【%str: =_%】
    :: 【老天 白  乾涛 老天】【包青天_白__乾涛_包青天】
    

    删除子字符串

    %str:subStr=%
    :: 可以认为是一种特殊的替换:将指定字符替换为空
    
    set str=包青天 白  乾涛 包青天
    echo 【%str:包青=%】【%str: =%】
    :: 【天 白  乾涛 天】【包青天白乾涛包青天】
    

    if/else 语句

    基本语法

    • 只有 if 语句时,if 语句的小括号是可选的
    • 有 else 语句时,if 语句必须带小括号,而 else 语句的小括号是可选的
    • if 条件不能加小括号,否则判断条件为 false
    SET /A c=5
    SET str=包青天
    
    if %c%==5 echo 只有 if 语句时,if 语句的小括号是可选的
    if %str%==包青天 (
        echo 如果换行的话必须加小括号,且左小括号不能换行--因为换行后就不是一条命令了,右括号不限制
        REM 注意:小括号内不能有 :: 格式的注释,可以有REM格式的注释(因为REM是命令)
    )
    :: 【==】既可以用来判断数值型,也可以用来判断字符串
    
    if [%1]==[] (echo 呵呵) else echo 有 else 语句时,if 语句必须带小括号,而 else 语句小括号可选
    if ([%1]==[]) (echo 呵呵) else (echo if 条件不能加小括号,否则判断条件为 false)
    

    嵌套 if 语句

    if(condition1) if (condition2) do_something
    :: 只有当条件1和条件2都满足时,才会执行 do_something 块中的代码
    

    if errorlevel

    环境变量 errorlevel 的初始值为0,当一些命令执行不成功,就会返回一个数值,如:1 ,2 等。

    注意:IF ERRORLEVEL 是用来测试它的上一个DOS命令的返回值的,注意只是上一个命令的返回值,而且返回值必须依照从大到小次序顺序判断。

    if ERRORLEVEL nubmer commend
    
    copy %0 new_file.bat
    if errorlevel 0 echo 命令成功完成
    
    copy %0 new/file.bat
    if errorlevel 1 echo 命令失败
    

    goto 语句

    @echo off & setlocal enabledelayedexpansion
    SET /A a=0
    
    :add
    set /A a+=1 & echo echo a当前的值为:%a%,a+1后的值为:!a!
    
    if %a% LSS 3 (
        goto :add
    ) else (
        goto :end
    )
    
    :end
    echo 执行完毕,a的值为:!a!
    

    运算符

    赋值运算符

    SET /A a=3
    SET /A a+=5
    echo %a%
    :: 其他类似的运算还有【a-=5】【a*=5】【a/=5】【a%=5】
    

    算术运算符

    SET /A a=5
    SET /A b=3
    
    SET /A c=%a%+%b%
    SET /A d=%a%-%b%
    SET /A e=%b%*%a%
    SET /A f=%b%/%a%
    SET /A g=%a%/%b%
    SET /A h=%b%%%%a%
    SET /A i=%a%%%%b%
    
    echo 【%c%】【%d%】【%e%】【%f%】【%g%】【%h%】【%i%】
    :: 【8】【2】【15】【0】【1】【3】【2】
    

    关系运算符

    SET /A a=5
    SET /A b=10
    
    if %a% EQU %b% echo 相等
    if %a% NEQ %b% echo 不相等性
    if %a% LSS %b% echo 左小于右
    if %a% LEQ %b% echo 左小于等于右
    if %a% GTR %b% echo 左大于右
    if %a% GEQ %b% echo 左大于等于右
    

    逻辑运算符

    • 批处理语言配备了一整套布尔逻辑运算符,如ANDORXOR,但只适用于二进制数字
    • 对于TRUEFALSE没有任何值
    • 可用于条件的唯一逻辑运算符是NOT运算符
    • 为非二进制数字实现AND/OR运算符的方法是使用嵌套的IF条件或goto语句

    逻辑非

    SET /A a=5
    IF NOT %a%==6 echo 逻辑非运算符NOT的使用
    

    逻辑与

    借助 if 语句实现

    SET /A a=5
    if %a% LSS 6 (
        if %a% GTR 4 (
            echo 嵌套if实现and的功能
        )
    )
    if %a% LSS 6 if %a% GTR 4 echo 嵌套if实现and的功能
    

    借助 goto 语句实现

    SET /A a=5
    
    if not %a% LSS 6 goto end
    if not %a% GTR 4 goto end
    :: 为了保持和上面if的结构一致,上面是用了两个not,实际肯定是可以不用not的
    goto and_function
    
    :and_function
    echo 嵌套if实现and的功能
    :end
    echo end
    

    逻辑或

    逻辑或实现起来比逻辑与还要复杂一些,一般都需要借助 goto 语句来实现!

    不借助 goto 语句实现的情况

    这种方式只适合满足条件时要执行的命令比较少的场景,否则会有大量的冗余代码

    SET /A a=3
    IF %a% LSS 4 (
        echo 如果满足条件一,则执行n条命令
    ) else IF %a% GTR 6 (
        echo 否则,如果满足条件二,也会执行相同的n条命令
    )
    IF %a% LSS 4 (echo 满足条件) else IF %a% GTR 6 (echo 满足条件)
    

    借助 goto 语句实现

    SET /A a=5
    
    IF %a% LSS 4 goto or_function
    IF %a% GTR 6 goto or_function
    goto end
    
    :or_function
    echo 嵌套if实现or的功能
    :end
    echo end
    

    数组

    数组类型并没有明确定义为批处理脚本中的类型,但可以模拟出来,但是有些功能使用起来会有诸多限制。

    白哥说:其实批处理脚本中的数组就是多个名称类似的变量,其本身没有任何特性或语法,只不过因为这些变量的格式比较像C、Java中的数组,而数组又是那么深入人心,所以我们将其当做数组来看待了而已。

    数组元素

    其实就是一系列相互之间没任何关系的变量!

    set a[0]=10
    set a[1]=1
    set a[1]=11
    set a[3]=14
    
    echo 【%a[0]%】【%a[1]%】【%a[2]%】【%a[3]%】【%a[4]%】
    :: 【10】【11】【值不确定】【14】【值不确定】
    :: 数组中的每个元素都需要使用set命令专门定义
    :: 注意,未定义的元素的值是无法确定的,并不一定是没有值(虽然大部分情况都是没有defined、也没有值的)!
    

    数组元素下标为变量

    数组元素下标为变量时,可以认为是:一个变量的名称取决于另一个变量!

    set a[0]=10
    set /a k=0
    
    :: 以下3种方式均可正确访问 a[k]
    echo %k%-%a[0]%
    call echo %k%-%%a[%k%]%%
    setlocal enabledelayedexpansion & echo %k%-!a[%k%]!
    :: 因为a[%k%]之前并没有定义(仅仅是定义了a[0]),所以必须`设置本地为延迟扩展`才能正常访问,且访问时必须使用!代替%
    

    数组的长度

    没有直接的函数来确定数组中元素的数量,只能通过遍历数组中的值列表手动计算

    set d[0]=10
    set d[1]=11
    set x=0
    
    :getArrayLength
    if defined d[%x%] (
       call echo %x%-%%d[%x%]%%
       set /a x+=1
       goto :getArrayLength
    )
    
    echo 数组长度为 %x%
    :: 注意,如果数组元素定义时不连续,这种方法计算出来的值可能就是错误的,核心在于上面的【defined】表达式
    

    在数组中创建结构

    set obj[0].Name=包青天
    set obj[0].ID=66
    set cur.Name=%obj[0].Name%
    
    echo 【%obj[0]%】【%obj[0].Name%】【%cur.Name%】【%cur.ID%】
    :: 【】【包青天】【包青天】【11】 cur.ID的值没有定义,所以打印结果是不确定的
    

    函数

    函数定义

    定义函数的格式

    :function_name 
    Do_something 
    EXIT /B 0
    :: EXIT语句用于确保函数正常退出
    

    调用函数的格式

    Call :function_name parameter1, parameter2… parametern
    :: 需要确保在主程序中放入【EXIT /B %ERRORLEVEL%】语句,以便将主程序的代码与函数分开
    

    函数的基本用法

    可以通过使用%~n(n代表参数的位置),来在函数内部访问参数

    亲测,完全可以省略掉其中的~符号

    set p=包青天
    CALL :function_1
    CALL :function_2 a p %p%
    EXIT /B %ERRORLEVEL%
    
    :function_1
    echo 调用了【%0】函数
    EXIT /B 0
    
    :function_2
    echo 调用了【%0】函数,参数为【%~1】【%2】【%3】,所有参数为【%*】
    EXIT /B 0
    

    函数的返回值

    函数可以通过简单地传递变量名称来处理返回值,这些变量名称将在调用该函数时保存返回值

    CALL :function_3 c & echo 一行代码时必须使用延迟变量【!c!】【%c%】
    CALL :function_3 d
    echo 不是一行代码时两种方式都可以【!d!】【%d%】
    
    set p=包青天
    CALL :function_3 %p% & echo 在函数中修改变量的值时,参数不是传入变量的引用【!p!】【%p%】
    CALL :function_3 p & echo 而是传入变量的名称【!p!】【%p%】
    EXIT /B %ERRORLEVEL%
    
    :function_3
    if NOT [%1]==[] set %1=baiqiantao
    EXIT /B 0
    

    参数作为输出参数时,此文件不要设置 setlocal enabledelayedexpansion,且函数内不要使用SETLOCAL、ENDLOCAL

    函数中的局部变量

    • 函数中的局部变量可以用来避免名称冲突,并保持函数本地的变量变化
    • 调用SETLOCAL命令后可确保命令处理器对所有环境变量进行备份,并可在调用ENDLOCAL命令后恢复
    • 当到达批处理文件结束时,即通过调用GOTO:EOFENDLOCAL被自动调用
    • 使用SETLOCAL对变量进行本地化允许在函数中自由使用变量名称,而不必担心与函数外使用的变量名称冲突
    • 可以递归地调用一个函数,使用SETLOCAL可以确保每个级别的递归都使用自己的一组变量,即使变量名被重用
    set x=Outer
    set y=Outer
    CALL :function_1 x y & echo 【!x!-!y!】--【%x%-%y%】
    CALL :function_2 x y & echo 【!x!-!y!】--【%x%-%y%】
    EXIT /B %ERRORLEVEL%
    
    :function_1
    set x=Inner1
    set %2=Inner1
    :: 当没有SETLOCAL时,以上两种set方式都能改变函数外的变量的值
    EXIT /B 0
    
    :function_2
    SETLOCAL
    set x=Inner2
    set %2=Inner2
    :: 当有SETLOCAL时,函数内部对变量的修改不影响函数外部的变量的值
    ENDLOCAL
    EXIT /B 0
    

    2019-12-30

  • 相关阅读:
    Lesson 2 :
    Session 1 : 笔记
    SpringBoot 3 : 单元测试和开发环境调试
    SpringBoot 2 : 网络配置
    MS leetcode 题目
    研二上末
    时不我待
    Do, I do!
    LeetCode 精选 TOP 面试题
    基于attractor landscape研究疾病发展及药物研发
  • 原文地址:https://www.cnblogs.com/baiqiantao/p/12122023.html
Copyright © 2020-2023  润新知