shell脚本编程进阶

shell脚本编程进阶:
            循环:
                 for 变量名 in 列表;do
                     循环体
                 done
                 列表生成方式:
                    (1) 直接给出列表
                    (2) 整数列表:
                        (a) {start..end}
                        (b) $(seq [start [step]] end)
                    (3) 返回列表的命令
                        $(COMMAND)
                    (4) 使用glob,如:*.sh
                    (5) 变量引用
                        $@, $*

                特殊格式:
                    双小括号方法,即((…))格式,也可以用于算术运算
                    双小括号方法也可以使bash Shell实现C语言风格的变量操作
                        I=10
                        ((I++))
                    for循环的特殊格式:
                    for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
                    do
                        循环体
                    done
                    控制变量初始化:仅在运行到循环代码段时执行一次
                    控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断

                例:
                    (1)for((i=1;i<=10;i++));  
                        do   
                            echo $(expr $i \* 3 + 1);  
                        done

                    (2)for i in $(seq 1 10) /{1..10}
                        do   
                            echo $(expr $i \* 3 + 1);  
                        done 

                while循环:
                    while CONDITION; do
                        循环体
                    done

                    while循环的特殊用法(遍历文件的每一行)
                        while read line; do
                            循环体
                        done < /PATH/FROM/SOMEFILE
                例:
                    while read -r  f1 f2 f3    #将文件内容分为三列
                    do
                          echo "file 1:$f1 ===> file 2:$f2 ===> file 3:$f3"   #按列输出文件内容
                    done < "$file"

                select循环与菜单:
                    select variable in list
                    do
                        循环体命令
                    done

                    用户输入被保存在内置变量 REPLY 中
                    select 是个无限循环,因此要记住用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环
                    select 经常和 case 联合使用


               until循环:
                    until CONDITION; do
                        循环体
                    done

                    进入条件: CONDITION 为false
                    退出条件: CONDITION 为true

                continue:
                    continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
                    while CONDTIITON1; do
                        CMD1
                        ...
                        if CONDITION2; then
                            continue
                        fi
                        CMDn
                        ...
                     done

                 break:
                     break [N]:提前结束第N层循环,最内层为第1层
                    while CONDTIITON1; do
                        CMD1
                        ...
                        if CONDITION2; then
                        break
                        fi
                        CMDn
                        ...
                    done

                shift [n]:
                    用于将参量列表 list 左移指定次数,缺省为左移一次。
                    参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用到 shift

            函数:function
                函数由两部分组成:函数名和函数体
                语法一:
                    f_name (){
                        ...函数体...
                    }
                语法二:
                    function f_name {
                        ...函数体...
                    }
                语法三:
                    function f_name () {
                        ...函数体...
                    }

                函数的定义和使用:
                    可在交互式环境下定义函数
                    可将函数放在脚本文件中作为它的一部分
                    可放在只包含函数的单独文件中

                函数有两种返回值:
                    (1) 使用echo等命令进行输出
                    (2) 函数体中调用命令的输出结果

                函数的退出状态码:
                    (1) 默认取决于函数中执行的最后一条命令的退出状态码
                    (2) 自定义退出状态码,其格式为:
                        return 从函数中返回,用最后状态命令决定返回值
                        return 0 无错误返回
                        return 1-255 有错误返回

                创建函数文件:
                    定位函数文件并载入shell的格式
                        . filename 或 source filename 
                    注意:此即<点> <空格> <文件名>  这里的文件名要带正确路径

                删除shell函数:
                    现在对函数做一些改动后,需要先删除函数,使其对shell不可用。使用unset命令完成删除函数
                    命令格式为:
                        unset function_name

                    环境函数
                        使子进程也可使用
                            声明:export -f function_name
                            查看:export -f 或 declare -xf
                函数参数:
                    传递参数给函数:调用函数时,在函数名后面以空白分隔给定参数列表即可;
                    例如:
                        “testfunc arg1 arg2 ...”
                    在函数体中当中,可使用$1, $2, ...调用这些参数;还可以使用$@, $*, $#等特殊变量

                函数变量:
                    变量作用域:
                        环境变量:当前shell和子shell有效
                        本地变量:只在当前shell进程有效,为执行脚本会启动专用子shell进程;因此,本地变量的作用范围是当前shell                          脚本程序文件,包括脚本中的函数
                        局部变量:函数的生命周期;函数结束时变量被自动销毁
                    注意:如果函数中有局部变量,如果其名称同本地变量,使用局部变量
                    在函数中定义局部变量的方法
                        local NAME=VALUE
                fork炸弹:
                    fork炸弹是一种恶意程序,它的内部是一个不断在fork进程的无限循环,实质是一个简单的递归程序。由于程序是递                      归的,如果没有任何限制,这会导致这个简单的程序迅速耗尽系统里面的所有资源

                    函数实现
                        :(){ :|:& };:
                        bomb() { bomb | bomb & }; bomb

            信号捕捉trap:
                trap '触发指令' 
                    信号进程收到系统发出的指定信号后,将执行自定义指令,而不会执行原操作
                trap '' 信号
                    忽略信号的操作
                trap '-' 信号
                    恢复原信号的操作
                trap -p
                    列出自定义信号操作
                trap finish EXIT
                    当脚本退出时,执行finish函数

                例:
                #!/bin/bash
                trap 'echo “signal:SIGINT"' int
                trap -p
                for((i=0;i<=10;i++))
                do
                     sleep 1
                     echo $i
                done
                trap '' int
                trap -p
                for((i=11;i<=20;i++))
                do
                     sleep 1
                     echo $i
                done
                trap '-' int
                trap -p
                for((i=21;i<=30;i++))
                do
                     sleep 1
                     echo $i
                done

            数组:
                数组名和索引
                    索引:编号从0开始,属于数值索引
                    注意:索引可支持使用自定义的格式,而不仅是数值格式,即为关联索引,
                bash4.0版本之后开始支持
                    bash的数组支持稀疏格式(索引不连续)

                声明数组:
                    declare -a ARRAY_NAME
                    declare -A ARRAY_NAME: 关联数组
                    注意:两者不可相互转换

                数组元素的赋值
                    (1) 一次只赋值一个元素
                        ARRAY_NAME[INDEX]=VALUE
                        weekdays[0]="Sunday"
                        weekdays[4]="Thursday"
                    (2) 一次赋值全部元素
                        ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
                    (3) 只赋值特定元素
                        ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
                    (4) 交互式数组值对赋值
                        read -a ARRAY

                    显示所有数组:declare -a 

                引用数组:
                    引用数组元素
                        ${ARRAY_NAME[INDEX]}
                        注意:省略[INDEX]表示引用下标为0的元素
                    引用数组所有元素
                        ${ARRAY_NAME[*]}
                        ${ARRAY_NAME[@]}
                    数组的长度(数组中元素的个数)
                        ${#ARRAY_NAME[*]}
                        ${#ARRAY_NAME[@]}
                    删除数组中的某元素:导致稀疏格式
                        unset ARRAY[INDEX]
                    删除整个数组
                        unset ARRAY

                数组数据处理:
                    引用数组中的元素:
                        数组切片:${ARRAY[@]:offset:number}
                            offset: 要跳过的元素个数
                            number: 要取出的元素个数
                            取偏移量之后的所有元素
                        ${ARRAY[@]:offset}
                    向数组中追加元素:
                        ARRAY[${#ARRAY[*]}]=value

                    关联数组:
                        declare -A ARRAY_NAME
                        ARRAY_NAME=([idx_name1]='val1' [idx_name2]='val2‘...)
                        注意:关联数组必须先声明再调用

            字符串处理:
                ${#var}:
                    返回字符串变量var的长度
                ${var:offset}:
                    返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,offset的取值在0 到                      ${#var}-1 之间(bash4.2后,允许为负值)
                ${var:offset:number}:
                    返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分
                ${var: -length}:
                    取字符串的最右侧几个字符
                    注意:冒号后必须有一空白字符
                ${var:offset:-length}:
                    从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容
                ${var: -length:-offset}:
                    先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容
                    注意:-length前空格


               基于模式取子串
                    ${var#*word}:其中word可以是指定的任意字符
                        功能:自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现word字符串                         (含)之间的所有字符
                    ${var##*word}:同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word指定的字符之间的所有内容
                示例:
                    file=“var/log/messages”
                    ${file#*/}: log/messages
                    ${file##*/}: messages

                ${var%word*}:其中word可以是指定的任意字符
                    功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删除字符串最后一个字符向左至第一次出现                      word字符串(含)之间的所有字符
                    例:
                        file="/var/log/messages"
                        ${file%/*}: /var/log
                ${var%%word*}:同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符
                示例:
                    url=http://www.magedu.com:80
                    ${url##*:} 80
                    ${url%%:*} http

                查找替换
                    ${var/pattern/substr}:查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之
                    ${var//pattern/substr}: 查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之
                    ${var/#pattern/substr}:查找var所表示的字符串中,行首被pattern所匹
                    ${var/%pattern/substr}:查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之

                查找并删除
                    ${var/pattern}:删除var表示的字符串中第一次被pattern匹配到的字符串
                    ${var//pattern}:删除var表示的字符串中所有被pattern匹配到的字符串
                    ${var/#pattern}:删除var表示的字符串中所有以pattern为行首匹配到的字符串
                    ${var/%pattern}:删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串

                字符大小写转换
                    ${var^^}:把var中的所有小写字母转换为大写
                    ${var,,}:把var中的所有大写字母转换为小写

            高级变量:
                Shell变量一般是无类型的,但是bash Shell提供了declare和typeset两个命令用于指定变量的类型,两个命令是等价的
                declare [选项] 变量名
                选项:
                    -r 声明或显示只读变量
                    -i 将变量定义为整型数
                    -a 将变量定义为数组
                    -A 将变量定义为关联数组
                    -f 显示已定义的所有函数名及其内容
                    -F 仅显示已定义的所有函数名
                    -x 声明或显示环境变量和函数
                    -l 声明变量为小写字母 declare –l var=UPPER
                    -u 声明变量为大写字母 declare –u var=lower

            eval命令:
                eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变                    量.该命令对变量进行两次扫描
                示例:
                    [root@server ~]# CMD=whoami
                    [root@server ~]# echo $CMD
                        whoami
                    [root@server ~]# eval $CMD
                        root
                    [root@server ~]# n=10
                    [root@server ~]# echo {0..$n}
                        {0..10}
                    [root@server ~]# eval echo {0..$n}
                         0 1 2 3 4 5 6 7 8 9 10
            间接变量引用:
                bash Shell提供了两种格式实现间接变量引用
                    eval tempvar=\$$variable1
                    tempvar=${!variable1}
                    示例:
                        [root@server ~]# N=NAME
                        [root@server ~]# NAME=wangxiaochun
                        [root@server ~]# N1=${!N}
                        [root@server ~]# echo $N1
                            wangxiaochun
                        [root@server ~]# eval N2=\$$N
                        [root@server ~]# echo $N2
                            wangxiaochun

            临时文件创建:
                mktemp命令:创建并显示临时文件,可避免冲突
                mktemp [OPTION]... [TEMPLATE]
                    TEMPLATE: filenameXXX
                                X至少要出现三个
                    OPTION:
                        -d: 创建临时目录
                        -p DIR或--tmpdir=DIR:指明临时文件所存放目录位置

                示例:
                    mktemp /tmp/testXXX
                    tmpdir=`mktemp –d /tmp/testdirXXX`
                    mktemp --tmpdir=/testdir testXXXXXX

            安装复制文件:
                install命令:
                    install [OPTION]... [-T] SOURCE DEST 单文件
                    install [OPTION]... SOURCE... DIRECTORY
                    install [OPTION]... -t DIRECTORY SOURCE...
                    install [OPTION]... -d DIRECTORY...创建空目录
                选项:
                    -m MODE,默认755
                    -o OWNER
                    -g GROUP

                示例:
                    install -m 700 -o wang -g admins srcfile desfile
                    install –m 770 –d /testdir/installdir 

            expect介绍:
                expect 是由Don Libes基于Tcl( Tool Command Language )语言开发的,主要应用于自动化交互式操作的场景,借                    助Expect处理交互的命令,可以将交互过程如:ssh登录,ftp登录等写在一个脚本上,使之自动化完成。尤其适用于                    需要对多台服务器执行相同操作的环境中,可以大大提高系统管理人员的工作效率
                
                expect 语法:
                    expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
                选项
                    -c:从命令行执行expect脚本,默认expect是交互地执行的
                         示例:expect -c 'expect "\n" {send "pressed enter\n"}
                    -d:可以输出输出调试信息
                         示例:expect -d ssh.exp

                expect中相关命令:
                    spawn:启动新的进程
                    send:用于向进程发送字符串
                    expect:从进程接收字符串
                    interact:允许用户交互
                    exp_continue 匹配多个字符串在执行动作后加此命令

                单一分支模式语法:
                    expect “hi” {send “You said hi\n"}
                    匹配到hi后,会输出“you said hi”,并换行

                多分支模式语法:
                    expect "hi" { send "You said hi\n" } \
                        "hehe" { send "Hehe yourself\n" } \
                        "bye" { send "Good bye\n" }

                    匹配hi,hello,bye任意字符串时,执行相应输出。等同如下:
                    expect {
                        "hi" { send "You said hi\n"}
                        "hehe" { send "Hehe yourself\n"}
                        "bye" { send "Good bye\n"}
                    }
                例:
                    变量:
                        #!/usr/bin/expect
                        set ip 192.168.8.100
                        set user root
                        set password magedu
                        set timeout 10
                        spawn ssh $user@$ip
                        expect {
                             "yes/no" { send "yes\n";exp_continue }
                             "password" { send "$password\n" }
                        }
                        interact

                    shell脚本调用:
                        #!/bin/bash
                        ip=$1
                        user=$2
                        password=$3
                        expect <<EOF
                        set timeout 20
                        spawn ssh $user@$ip
                        expect {
                             "yes/no" { send "yes\n";exp_continue }
                             "password" { send "$password\n" }
                        }
                        expect "]#" { send "useradd hehe\n" }
                        expect "]#" { send "echo magedu |passwd --stdin hehe\n" }
                        expect "]#" { send "exit\n" }
                        expect eof
                        EOF 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值