zoukankan      html  css  js  c++  java
  • 脚本编程(一)

    脚本编程(一)

    啰里啰唆:每周的最后一天都特别难受。墨迹扣不出文章。

    一、概况

    注释是以#开都的,#开头不一定都是注释

    SHELL是解释型语言

    SHELL脚本第一句以#!/bin/bash开头

    SHELL脚本需要具有执行权限

    一般以.sh结尾

    别名在脚本中无效。在脚本中不能使用别名。

    bash使用技巧:

    -n 检查语法,无法无法检测处命令错误,同时只是检查语法不会真正执行脚本。

    -x 逐行执行,逐行显示执行结果

    脚本中的错误:

    1、语法错误,会导致后续的命令无法继续执行。可以通过bash -n选项来检查

    提示的错误行不一定是准确的。

    2、命令错误,后续的命令还可以继续执行。无法通过bash -n 选项来检查错误,可以使用set -e或者set -o errexit来设定遇到错误命令后退出

    3、逻辑错误,只能使用bash -x选项来检查错误。

    变量:

    变量表示命名的内存空间,讲数据放在内存空间中,通过 "$变量名" 引用,从而获取数据

    内置环境变量:

    PS1 SHELL HASTNAME $$ $?

    自定义变量:

    [set] NAME=VALUE set可以省略

    变量类型:

    字符型:默认都是字符型

    数值:整型、 bash不支持浮点型

    静态编译语言,使用变量前,先声明变量类型,之后类型不能改变,在编译时执行检查,JAVA C

    动态编译语言:不用事先声明,可以随时改变变量类型,SHELL PYTHON

    强类型语言:不同类型的操作数,必须经过强制转换成同一类型的变量后才能运算

    弱类型语言:不同类型的操作数,会隐式转换数据类型,如SHELL

    shell中变量命令规则

    变量名不用实现声明

    变量名不能和系统已经定义好的变量同名

    变量名不能和系统的内外部命令同名

    变量名不能和系统定义好的关键字同名,如:if else case for

    变量名不能以数字开头

    变量名不支持短横线-

    变量名需要见名知意,最好用英语名,最好不要命拼音,不要用拼英缩写

    统一命名规则:驼峰命名法,大驼峰studentName     小驼峰studentName

    变量名大写

    局部变量小写

    函数名小写

    普通变量,生效范围是当前shell进程;对当前shell之外的其它进程(包括当前shell的子进程)均无效。

    环境变量,生效范围是当前shell进程及其子进程

    本地变量,生效范围进士当前shell进程中某个代码片段,通常指函数。

    变量赋值的时候等号左右不要有空格: NAME="value"    如果赋值中有空格需要使用引号引起来。

    可以把文件路径赋值给变量。

    特殊用法参考以下示例:

    [root@CentOS8 /]# FILE=/*
    [root@CentOS8 /]# echo $FILE
    /bin /boot /data /dev /etc /home /lib /lib64 /media /mnt /opt /proc /root /run /sbin /srv /sys /@System.solv /tmp /usr /var
    /*
    [root@CentOS8 /]# ls -d $FILE
    /bin   /data  /etc   /lib    /media  /opt   /root  /sbin  /sys           /tmp  /var
    /boot  /dev   /home  /lib64  /mnt    /proc  /run   /srv   /@System.solv  /usr
    [root@CentOS8 /]# ls -d "$FILE"

    变量引用  $NAME   ${NAME}

    变量引用的时候,加上双引号会保留原始的回车符等隐式字符,

    不加上双引号默认会去掉回车符并以空格代替。

    看以下示例 {

    [root@CentOS8 ~]# NUM=`seq 10`
    [root@CentOS8 ~]# echo "$NUM"
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [root@CentOS8 ~]# echo $NUM
    1 2 3 4 5 6 7 8 9 10
    [root@CentOS8 ~]#
    

    注意:变量赋值时临时生效,当退出终端后,变量会自动删除;脚本中的变量会随着脚本结束自动删除。

     

    env可以显示所有已经定义好的环境变量

    export不跟任何选项,也可以显示所有已经定义的环境变量

    declare -x 也可以显示所有已经定义的环境变量

    set可以显示所有已经定义好的所有变量

    unset NAME可以取消变量定义

    unset NAME1 NAME2 NAME3...取消多个变量

    无法在子shell中使用父shell中定义的本地变量,可以使用exportdeclare -x把变量声明成环境变量,就可以在子shell(包括孙子进程)中调用父shell中定义的环境变量。但是无法让父进程继承子进程的

    变量,孙子进程可以继承子进程的环境变量。

    $BASHPID 显示当前进程的PID

    $PPID 显示父进程的PID

    LANG 语言系环境变量

    MAIL 邮箱

    SHLVL shell的嵌套深度

    变量除了可以存字符,还可以存命令。$CMD的结果SHELL会当成命令执行。

    只读变量,定义后的只读变量不能修改和删除,只能退出重新登

    readonly NAME 定义只读变量

    declare -r NAME 定义只读变量

    位置变量:

    $0 表示命令本身,会包括路径

    $1 表示对应第一个参数,使用shift n替换

    $2 表示对应第二个参数,使用shift n替换

    ...

    ${10} 表示对应的第十个参数,不能直接写成$10

    ${11} 表示对应的第十一个参数,不能直接写成$11

    $* 表示所有参数,会把各个变量看成统一整体,只有双引号$*"$@"才有区别

    $@ 表示所有参数,会把各个变量看成独立个体,只有双引号$*"$@"才有区别

    $# 表示参数个数

    $? 判断上一条执行状态的执行结果

    $_ 前一个命令的最后一个参数

    set -- 清楚所有位置变量

    [root@CentOS7 2]# cat arg.sh
    #!/bin/bash
    #
    echo "1st is $1"
    echo "2st is $2"
    echo "3st is $3"
    echo "10st is ${10}"
    echo "10st is $10"
    echo "11st is ${11}"
    echo "11st is $11"
    echo "The number of `basename $0` is $#"
    echo "All args are $*"
    echo "All args are $@"
    .
    /arg2.sh $* ;echo '$*' ./arg2.sh $@ ;echo '$@' ./arg2.sh "$*" ;echo '"$*"' ./arg2.sh "$@" ;echo '"$@"'
    [root@CentOS7 2]# cat arg2.sh #!/bin/bash # echo -n "$1 " [root@CentOS7 2]# ./arg.sh {a..z} 1st is a 2st is b 3st is c 10st is j 10st is a0 11st is k 11st is a1 The number of arg.sh is 26 All args are a b c d e f g h i j k l m n o p q r s t u v w x y z All args are a b c d e f g h i j k l m n o p q r s t u v w x y z a $* a $@ a b c d e f g h i j k l m n o p q r s t u v w x y z "$*" a "$@" [root@CentOS7 2]#

    命令行展开

    命令行展开优先级

    1、把命令行分成单个命令词

    2、展开别名

    3、展开大括号的声明{}

    4、展开波浪线声明~

    5、命令替换$()或··

    6、再次把命令行分成命令词

    7、展开文件通配符

    8、准备I/O重定向

    9、运行命令

    防止扩展

    使用反斜线会是随后的字符按愿意执行

    脚本安全和set

    she命令,地址shell环境

    $- 以关键字形式显示系统启用功能

    +表示禁用,-表示启用

    h 表示hash,可以set +h选项关闭hash

    i 交互式,说明当前shell是个交互是shell

    m 表示启用job control来控制进程的停止

    B 表示启用大括号扩展

    H HISTORY,表示可以展开命令历史列表

      $_ 前一个命令的最后一个参数

    set命令 修改环境变量

    -o 打开关闭某些选项,如果后面不跟任何选项表示显示以shell启用的某些功能

    set -o 表示启用

    set +o  表示禁用

    -e 等同于 -o errexit遇到命令出错就退出

    -u 是否使用没有定义的变量,相当于-o nounset

    -x 单步执行

      exit命令

        用户可以在脚本中使用以下命令自定义退出状态码

            exit [n]

        脚本中一旦遇到exit命令,脚本会立即终止,然后返回状态码

        如果exit未指定退出码,整个脚本的最终状态码取决于最后一条命令的状态码。

        例:{示例说明演示未指定退出码的情况

    [root@CentOS7 2]# cat exit.sh
    #!/bin/bash
    #
    echo haha
    ech haha
    exit
    [root@CentOS7 2]# ./exit.sh
    haha
    ./exit.sh: line 4: ech: command not found
    [root@CentOS7 2]# echo $?
    127

    printf命令

    printf "指定的格式" 文本1  文本2.。。 按照指定格式显示指定文本

    %s 字符串格式,%-#.##s中,#表示显示字符宽度,数字不足的用空格补足,##表示显示小数个数,-表示左对齐

    %f 浮点型格式

    %b 相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转义

    %d  | %i 十进制整数

    %c ASCII字符,即显示对应参数的第一个字符

    %o 八进制显示

    %u 不带正负号的十进制显示

    %x 小写的十六进制显示,即a-f

    %X 大写的十六进制显示,即A-F

    %% 表示%本身

    转义字符:

    a 警告字符,会发一声响

     后退一格

    f 换页

    换行

    回车

    横向制表符

    v 纵向制表符

    \ 表示本身

    二、算数运算

    算数运算符

    +

    -

    *

    /

    % 取模,求余数

    ** 乘方

    进行算数表达式

    let $M+$N 不用带$,带上也没问题

    let M++ M自增,与++M的区别是前者是先引用后自增,后者是先自增后引用

    let N-- N自减,与--N的区别是前者是先引用后自减,后者是先自减后引用

    $[$M+$N] 不用带$,带上也没问题

    $(($M+$N)) 不用带$,带上也没问题

    expr $M + $N 在运算符两边要有空格,在运算乘法的时候需要转移即*

    declare -i VAR 可以使用declare -i把变量声明成整数,然后就可以直接运算了

     

    三、逻辑运算

     1&&1=1   1&&0=0   0&&1=0    0&&0=0 任何数与0相与都为假

     1||1=1   1||0=1   0||1=1    0||0=0 任何数与1相或都为真

     !1=0     !0=1

    异或  1^0=1   1^1=0    0^0=0     0^1=0 异或是用二进制进行运算。异或的两个值,相同为假,不同为真

    两个运算数异或得出的值,此值在与两个运算数其中任何一个再异或,必定得出另一个运算数

    示例演示用异或互换两个变量的值

    #!/bin/bash
    # i
    =10 j=20 echo "i=$i;j=$j" #i中的值现在已经是i与j的异或值 i=$[i^j] #下句的意思是用上一句得出的异或值i,与运算数j 再次进行异或,会得出另一个运算数 j=$[i^j] #下句的意思是用上一句得出的异或值j再次与第一句中得出的异或值i进行异或,会得出另一个 运算数 i=$[i^j] echo "i=$i;j=$j"

    短路运算

    短路与:CMD1&&CMD2

    第一个CMD1结果为0,总的结果必定为0,因此不需要执行CMD2

    第一个CMD1结果为1,第二个CMD2必须要参与运算,才能得到最终结果

    短路或:CMD1||CMD2

    第一个CMD1结果为1,总的结果必定为1,因此不需要执行CMD2

    第一个CMD1结果为0,第二个CMD2必须要参与运算,才能得到最终结果

    四、条件测试

    条件测试命令

    test EXPRESSION

    [ EXPRESSION ] 判断式必须有空格。等同于test

    [[ EXPRESSION ]]

    变量测试

    [ -v VAR ] 判断变量VAR是否已经定义,True if the shell variable VAR is set.

    [ -R VAR ] 判断变量VAR是否已经定义并且已经引用,True if the shell variable VAR is set and is a name reference.

    数值测试     进行数值判断的时候不能有非数字

    -eq 相等

    -ne 不相等

    -lt 小于

    -le 小于等于

    -gt 大于

    -ge 大于等于

    字符串测试

    -z 测试变量是否为空或者没赋值,变量未定义 变量里面是空值 都为真,但是在以用变量的时候需要加上双引号。True if string is empty.例:n="";[ -z "$n" ];echo $?

    -n 判断变量是否为非空,在引用变量的时候必须加上双引号 True if string is not empty.: [ -n "$mm" ]

    [STRING] 判断式中什么也不见,默认是指判断变量是否为非空。True if string is not empty.

    = 判断字符串是否相等,等号两边都有空格,True if the strings are equal.

    != 判断字符串是否不相等,不等号两边都有空格,True if the strings are not equal.

    > 前一个字符串的长度大于后一个字符串,True if STRING1 sorts after STRING2 lexicographically.

    < 前一个字符串的长度小于后一个字符串,True if STRING1 sorts before STRING2 lexicographically.

    [ $mm ] 如果什么也不跟,是为了判断变量mm长度是否非零,True if string is not empty.

    示例演示[ $mm ]

    [root@CentOS8 7]# mm=""
    [root@CentOS8 7]# [ $mm ] && echo haha
    [root@CentOS8 7]# mm="123"
    [root@CentOS8 7]# [ $mm ] && echo haha
    haha}

      [[ ]] 双中括号的时候里面可以用正则表达式,双中括号也支持通配符,一般情况下使用单中括号

       [[ "$FILE" == *.log ]] 在双中括号中== 后面接通配符,判断FILE文件是不是log结尾

       [[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]  在双中括号中=~ 后面接正则表达式

       结论:[[ == ]]这种写法中,==右侧的* 如果想做通配符,不要加"",只想做*本身含义,需要转移或者加上双引号

        示例演示通配符 {[root@CentOS8 7]# mm=hh.tt

    [root@CentOS8 7]# [ "$mm" == "*.tt" ] && echo haha
    [root@CentOS8 7]# [ $mm == "*.tt" ] && echo haha
    [root@CentOS8 7]# [[ $mm == "*.tt" ]] && echo haha
    [root@CentOS8 7]# [[ "$mm" == "*.tt" ]] && echo haha
    [root@CentOS8 7]# [[ "$mm" == "*.tt" ]] && echo haha
    [root@CentOS8 7]# [[ "$mm" == *.tt ]] && echo haha
    haha

      =~==详细使用介绍{

    #通配符
    
    [root@centos8 ~]#FILE=test.log
    [root@centos8 ~]#[[ "$FILE" == *.log ]]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#FILE=test.txt
    [root@centos8 ~]#[[ "$FILE" == *.log ]]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#[[ "$FILE" != *.log ]]
    [root@centos8 ~]#echo $?
    0
    
    #正则表达式
    [root@centos8 ~]#[[ "$FILE" =~ .log$ ]]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#FILE=test.log
    [root@centos8 ~]#[[ "$FILE" =~ .log$ ]]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#N=100
    [root@centos8 ~]#[[ "$N" =~ ^[0-9]+$ ]]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#N=Magedu10
    [root@centos8 ~]#[[ "$N" =~ ^[0-9]+$ ]]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#IP=1.2.3.4
    [root@centos8 ~]#[[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#IP=1.2.3.4567
    [root@centos8 ~]#[[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#[[ $IP =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}
    ([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]
    [root@centos8 ~]#echo $?
    1
    
    #通配符
    [root@centos8 ~]#NAME="linux1"
    [root@centos8 ~]#[[ "$NAME" == linux* ]]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#[[ "$NAME" == "linux*" ]]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#NAME="linux*"
    [root@centos8 ~]#[[ "$NAME" == "linux*" ]]
    [root@centos8 ~]#echo $?
    0

    #结论:[[ == ]] == 右侧的 * 做为通配符,不要加“”,只想做为*, 需要加“” 或转义

    文件测试

    -a 文件是否存在,True if file exists.

    -e 文件是否存在 等同于-a, -e选项常用,True if file exists.

    -b 文件是否是块文件,True if file is block special.

    -c 文件是否是字符文件,True if file is character special.

    -d 判断是不是目录,True if file is a directory.

    -f 判断是不是普通文件,在判断软连接的时候,会追踪软连接指向的文件,True if file exists and is a regular file.

    -h -L 判断是不是软连接,True if file is a symbolic link.

    -p 判断是不是管道文件,True if file is a named pipe.

    -S 大写,判断是不是套接字文件

    文件新旧比较

    -ot old thanTrue if file1 is older than file2.

    -nt new thanTrue if file1 is newer than file2

    -ef 判断是不是硬链接,True if file1 is a hard link to file2.

    文件权限测试

    -w 判断文件是否有写权限,判断最终的权限,而不是看表面ll的显示结果,True if the file is writable by you.

    -x 判断文件是否有执行权限,判断最终的权限,而不是看表面ll的显示结果,True if the file is executable by you.

    -r 判断文件是否有读权限,判断最终的权限,而不是看表面ll的显示结果,True if file is readable by you.

    -u FILE 是否存在且拥有suid权限

    -g FILE 是否存在且拥有sgid权限

    -k FILE 是否存在且拥有sticky权限

    文件属性测试

    -s 小写,是否存在且非空,True if file exists and is not empty.

    -t 判断文件的文件描述符是否已经打开,True if FD is opened on a terminal.

    -N FILE 文件自从上一次被读取之后是否被修改过

    -O FILE 当前有效用户是否为文件属主

    -G FILE 当前有效用户是否为文件属组

    () 小括号中变量会在子进程中运行,同时会继承父进程中的变量值,但是起产生的结果不会影响父进程中的值

    {} 花括号中的变量不会在子进程中运行,会在当前进程中执行,其结果会影响话括号外面的变量,花括号内的最后公式需要以分号;结尾,花括号内两边有空格

    (){}都能将多个命令组合在一起,批量执行.

    组合测试条件

    [ EXPRESSION1 -a EXPRESSION2 ] 并且,表达式1和表达式2,结果才为真,True if both expr1 AND expr2 are true.

    [ EXPRESSION1 -o EXPRESSION2 ]  或者,表达式1和表达式2只要一个为真,结果就为真,会进行短路运算,True if either expr1 OR expr2 is true.

    [ ! EXPRESSION ]   取反,True if expr is false.

      -a-o选项只能在单中括号内使用,不能再[[ ]]内使用。

      COMMAND1 && COMMAND2 并且,短路与,代表条件性的AND THEN。如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2

      COMMAND1 || COMMAND2 或者,短路或,代表条件性的OR ELSE。如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2

      ! COMMAND ,取反

      如果&&||同时使用,一般情况下&&放在前面给,||放在后面。

    六、条件判断

    顺序执行:

      ;分号

    if语句

      单分支:

    if COMMANDS; then

    COMMANDS

    fi

      双分支:

    if EXPRIESSION;then

    COMMANDS

    else

    COMMANDS

    fi

      多分支:

    if EXPRIESSION;then

    COMMANDS

    elif EXPRIESSION; then

    COMMANDS

    elif EXPRIESSION; then

    COMMANDS

    fi

    case语句

    case WORD in

    [PATTERN])

    COMMAND

    ;;

    [PATTERN])

    COMMAND

    ;;

    *)

    COMMAND

    ;;

    esac

    PATTER式通配符模式

    * 任意长度任意字符

    任意一个字符

    [] 匹配中括号中的单个字符

    ^ 取反

  • 相关阅读:
    微软工具连接
    [转贴]生成缩略图
    突破验证,安装Media Player11.
    【转贴】Sourcecode and Code Snippets
    AppArch(一):User Interface
    【转】中国的OA要走的路还很长
    对WebService的在企业应用中的思考。
    [转贴]按文件类型获取其图标
    信息系统分析方法
    【转】WebService第一次调用正常,第二次调用超时的解决办法。
  • 原文地址:https://www.cnblogs.com/fengciaimei/p/12635551.html
Copyright © 2011-2022 走看看