Bat脚本学习-4:Oracle自动备份还原脚本

从同事那弄到一份Oracle自动备份还原的脚本,看上去很强大,苦在bat语法不熟,查了半天文档,先弄明白了一小段

@echo off

REM 在批处理中,我们可以用setloacl ENABLEDELAYEDEXPANSION这个命令来启用"延迟环境变量扩展"
REM 在我们启用了"延迟环境变量扩展"后,当CMD在解释涵有嵌套格式的命令时,他会把嵌套的命令一条一条的先执行一次,然后再进行匹配操作
REM 这样我们的赋值操作就会完成.并且再"延迟环境变量扩展"启用后,CMD会用!号来判断这是不是一个变量
REM 如没启用来变量用%name%这样的格式判断,启用后就用!name!这样的格式判断了,这个符号我们需要注意!
setlocal ENABLEDELAYEDEXPANSION

::读取配置文件
echo 正在读取配置文件...
set "base64=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="

REM 假如执行一个命令,但是不想在屏幕里看到这个命令的执行情况,可以使用"[命令]>nul"就可以屏蔽命令在屏幕上的输出
REM 但是有的命令执行会出错,即使用了">nul"也不能屏蔽命令产生的信息,所以就在后面加" 2>nul"这个
REM 就是"[命令]>nul+空格+2>nul",这样,不管命令是否正确的运行,都不会在屏幕看到这个命令所产生的屏幕显示了。
REM 此处作用是在系统目录下新建一个文件夹,如果已经存在会报错,但被nul屏弊了,不会看到错误提示的输出
md %windir%OracleAutoBackup >nul 2>nul

set configFile=%windir%OracleAutoBackupconfig.ini
set i=0
REM 文件不存在的话,就新建并输出一个换行符
REM .表示换行,>表示输出到文件
if not exist %configFile% echo.>%configFile%

REM delims=后面的字符的意识是,将文本每一行的内容以delims=后面的字符分割成若干列.
REM delims=后面可以是多个字符,可以是空格,也可以什么都没有.
REM 什么都没有代表什么呢?就是不以任何东西为分割符,也是整行的内容了.
REM 因为for默认是以,;和空格作分割符的, 所以一般要取得整行内容通常会用"delims="这样的形式来取消for的默认分割符.
for /f "delims=" %%x in (%configFile%) do (
    REM i为全局变量
    if !i!==0 set bak_hou=%%x
    if !i!==1 set bak_lot=%%x
    if !i!==2 set bak_dir=%%x
    REM gtr表示大于
    REM set/a表示数字运算
    REM call表示调用函数
    if !i! gtr 2 (
        set/a gup=!i!-2
        call :base64_str "%%x"
        set ora[!gup!]=!val!
    )
    set/a i+=1
)
cls

::取默认值
REM ^ 表示行首,"^step"仅匹配 "step hello world"中的第一个单词
REM $ 表示行尾,"step$"仅匹配 "hello world step"中最后一个单词
REM *号表示重复的次数为零次或者多次
REM ^[0-9]*$表示纯数字

REM || 可同时执行多条命令,当碰到执行正确的命令时,将不再执行后面的命令。如果一直没有正确的,则执行完毕
REM && 可同时执行多条命令,当碰到执行错误的命令时,将不再执行后面的命令。如果一直没有错误的,则执行完毕
REM &同时执行多条命令,不管命令是否执行成功

REM 所以这两句意思是如果是空,则赋值;如果是数字,则不赋值,保留原值
if "!bak_hou!"=="" set bak_hou=3
echo !bak_hou!|findstr "^[0-9]*$">nul || set bak_hou=3

if "!bak_lot!"=="" set bak_lot=7
echo !bak_lot!|findstr "^[0-9]*$">nul || set bak_lot=7

REM %cd%表示当前文件夹(执行时所在文件夹),%~dp0表示批处理文件所在文件夹
if "!bak_dir!"=="" set bak_dir=%cd%数据库备份

REM "delims=" 的含义是取消默认的分隔符,所以会把行上的内容照搬下来
REM 而 "tokens=*" 表示获取行上的所有内容,但是会忽略行首的所有空格。
REM %~fI - 将 %I 扩充到一个完全合格的路径名,这个I其实就是我们在FOR带入的变量,此处为x
for /f "tokens=*" %%x in ("!bak_dir!") do set bak_dir=%%~fx

if not exist !bak_dir! md !val! >nul 2>nul

::去掉格式错误的数据库连接配置项
set j=0
for %%i in (1,2,3,4,5,6,7,8,9) do (
    REM && 可同时执行多条命令,当碰到执行错误的命令时,将不再执行后面的命令。如果一直没有错误的,则执行完毕
    set ora[%%i]>nul 2>nul&& (
        REM set后面不赋值表示清空变量
        set ora_cur=
        
        REM usebackq 是一个增强型参数,当使用了这个参数之后,原来的for语句中第一个括号内的写法要做如下变动:
        REM 如果第一个括号里的对象是一条命令语句的话,原来的单引号'要改为后引号`;
        REM 如果第一个括号里的对象是字符串的话,原来的双引号"要改为单引号';
        REM 如果第一个括号里的对象是文件名的话,要用双引号"括起来
        
        REM tokens=1-3”表示1至3列,后面疑是%%a,怎么会是%%b?
        for /f "usebackq delims==. tokens=1-3" %%a in (`set ora[%%i]`) do set ora_cur=%%b
        set ora[%%i]=
        
        REM /表示转义的/
        echo !ora_cur!|findstr "/">nul 2>nul && echo !ora_cur!|findstr "@">nul 2>nul && (
            set/a j+=1
            set ora[!j!]=!ora_cur!
        )
    )
)

写了很多注释,以便理解

原文地址:https://www.cnblogs.com/liuyouying/p/7143289.html