bash-基础--数组和字符切片

                        数组

什么是数组?

    变量:存储单个元素的内存空间;

    数组:存储多个元素的连续的内存空间;

    数组名:整个数组只有一个名字;

    数组索引:编号从0开始;

    数组名[索引],  ${ARRAY_NAME[INDEX]}

注意:bash-4及之后的版本,支持自定义索引格式,而不仅仅是0,1,2,...数字格式;

     此类数组称之为“关联数组”





声明数组:

     declare  -a  NAME:声明索引数组;

     declare  -A  NAME:声明关联数组;



数组中元素的赋值方式:

        (1) 一次只赋值一个元素; ARRAY_NAME[INDEX]=value

        (2) 一次赋值全部元素;ARRAY_NAME=("VAL1"  "VAL2"  "VAL3"  ...)

        (3) 只赋值特定元素;ARRAY_NAME=([0]="VAL1"  [3]="VAL4" ...)

            注意:bash支持稀疏格式的数组;

        (4) read  -a  ARRAY_NAME  引用数组中的元素:${ARRAY_NAME[INDEX]}

            注意:引用时,只给数组名,表示引用下标为0的元素;




数组的长度(数组中元素的个数):

           ${#ARRAY_NAME[*]}

           ${#ARRAY_NAME[@]}


示例:生成10个随机数,并找出其中的最大值和最小值;

           

             #!/bin/bash
             #
                declare -a  rand
                declare -i max=0
            for i in {0..9}; do
                  rand[$i]=$RANDOM
                  echo ${rand[$i]}
                 [ ${rand[$i]} -gt $max ] && max=${rand[$i]}
            done

              echo "MAX: $max"




练习:定义一个数组,数组中的元素是/var/log目录下所有以.log结尾的文件;统计其下标为偶数的文件中的行数之和;

        

#!/bin/bash
        #
            declare -a files
            files=(/var/log/*.log)
            declare -i lines=0
        for i in $(seq 0 $[${#files[*]}-1]); do
            if [ $[$i%2] -eq 0 ]; then
                let lines+=$(wc -l ${files[$i]} | cut -d' ' -f1)
            fi
                done
        echo "Lines: $lines."


引用数组中的所有元素:

      ${ARRAY_NAME[*]}

      ${ARRAY_NAME[@]}


数组元素切片: ${ARRAY_NAME[@]:offset:number}

           offset:要路过的元素个数;

           number:要取出的元素个数;省略number时,表示取偏移量之后的所有元素;


向非稀疏格式数组中追加元素:ARRAY_NAME[${#ARRAY_NAME[*]}]=

删除数组中的某元素:unset  ARRAY[INDEX]


关联数组:

       declare  -A  ARRAY_NAME  注:声明一个数组变量

       ARRAY_NAME=([index_name1]="value1"  [index_name2]="value2" ...)




 

                          字串切片



bash的内置字符串处理工具:

     字符串切片:${var:offset:number}

    取字符串的子串;取字符趾的最右侧的几个字符:${var:  -length} 

                                                注意:冒号后必须有一个空白字符;


基于模式取子串:

1、${var#*word}:其中word是指定的分隔符;功能:自左而右,查找var变量所存储的字符串中,第一次出现的word分隔符,删除字符串开头至此分隔符之间的所有字符;

2、${var##*word}:其中word是指定的分隔符;功能:自左而右,查找var变量所存储的字符串中,最后一次出现的word分隔符,删除字符串开头至此分隔符之间的所有字符;


举例:mypath="/etc/init.d/functions"

3、${mypath##*/}:   functions

4、${mypath#*/}:  etc/init.d/functions

5、${var%word*}:其中word是指定的分隔符;功能:自右而左,查找var变量所存储的字符串中,第一次出现的word分隔符,删除此分隔符至字符串尾部之间的所有字符;

6、${var%%word*}:其中word是指定的分隔符;功能:自右而左,查找var变量所存储的字符串中,最后一次出现的word分隔符,删除此分隔符至字符串尾部之间的所有字符;


举例:mypath="/etc/init.d/functions"

7、${mypath%/*}:  /etc/init.d


举例:url=http://www.magedu.com:80

8、${url##*:}

9、${url%%:*}




查找替换:

1、${var/PATTERN/SUBSTI}:查找var所表示的字符串中,第一次被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串;

2、${var//PATTERN/SUBSTI}:查找var所表示的字符串中,所有被PATTERN所匹配到的字符串,并将其全部替换为SUBSTI所表示的字符串;

4、${var/#PATTERN/SUBSTI}:查找var所表示的字符串中,行首被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串;

5、${var/%PATTERN/SUBSTI}:查找var所表示的字符串中,行尾被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串;

    注意:PATTERN中使用glob风格和通配符;




查找删除:

1、${var/PATTERN}:以PATTERN为模式查找var字符串中第一次的匹配,并删除之;

2、${var//PATERN}

3、${var/#PATTERN}

4、${var/%PATTERN}




字符大小写转换:

1、${var^^}:把var中的所有小写字符转换为大写;

2、${var,,}:把var中的所有大写字符转换为小写;

3、变量赋值:

4、${var:-VALUE}:如果var变量为空,或未设置,那么返回VALUE;否则,则返回var变量的值; 

5、${var:=VALUE}:如果var变量为空,或未设置,那么返回VALUE,并将VALUE赋值给var变量;否则,     则返回var变量的值; 

6、${var:+VALUE}:如果var变量不空,则返回VALUE;

7、${var:?ERROR_INFO}:如果var为空,或未设置,那么返回ERROR_INFO为错误提示;否则,返回var值; 








写一个脚本:

ping命令去查看172.16.1.1-172.16.67.1范围内的所有主机是否在线;在线的显示为up, 不在线的显示down,分别统计在线主机,及不在线主机数;

分别使用for, while和until循环实现。

 for循环实现方式 

#!/bin/bash
                   #
                    declare -i uphosts=0
                    declare -i downhosts=0
                    for i in {1..17}; do
                        if ping -W 1 -c 1 172.16.$i.1 &> /dev/null; then
                            echo "172.16.$i.1 is up."
                            let uphosts+=1
                        else
                            echo "172.16.$i.1 is down."
                            let downhosts+=1
                        fi
                    done
                    echo "Up hosts: $uphosts, Down hosts: $downhosts."




while循环实现方式:

               

 #!/bin/bash
                    #
                            declare -i uphosts=0
                            declare -i downhosts=0
                            declare -i i=1
                        hostping() {
                            if ping -W 1 -c 1 $1 &> /dev/null; then
                                echo "$1 is up."
                                return 0
                            else
                                    echo "$1 is down."
                                    return 1
                            fi
                                }
                        while [ $i -le 67 ]; do
                            hostping 172.16.$i.1
                            [ $? -eq 0 ] && let uphosts++ || let downhosts++
                                let i++
                            done
                            echo "Up hosts: $uphosts, Down hosts: $downhosts."


写一个脚本,实现:

能探测C类、B类或A类网络中的所有主机是否在线;

                   

                           #!/bin/bash
                           #
                        cping() {
                                local i=1
                                while [ $i -le 5 ]; do
                                    if ping -W 1 -c 1 $1.$i &> /dev/null; then
                                            echo "$1.$i is up"
                                    else
                                            echo "$1.$i is down."
                                    fi
                                            let i++
                                            done
                                        }
                                bping() {
                                            local j=0
                                        while [ $j -le 5 ]; do
                                            cping $1.$j
                                            let j++
                                            done
                                          }
                                aping() {
                                            local x=0
                                        while [ $x -le 255 ]; do
                                            bping $1.$x
                                            let x++
                                            done
                                            }




信号捕捉trap




trap  'COMMAND'  SIGNALS  注:捕捉到 SIGNALS ,就执行'COMMAND'

   常可以进行捕捉的信号:HUP, INT(ctrl +c ) 

  


提示用户输入一个IP地址或网络地址;获取其网络,并扫描其网段;           

 信号捕捉示例:
                        #!/bin/bash
                        #
                        declare -a hosttmpfiles
                        trap  'mytrap'  INT
        
                        mytrap()  {
                                    echo "Quit"
                                    rm -f ${hosttmpfiles[@]}
                                    exit 1
                                    }
        
                        for i in {1..50}; do
                                tmpfile=$(mktemp /tmp/ping.XXXXXX)
                            if ping -W 1 -c 1 172.16.$i.1 &> /dev/null; then
                                echo "172.16.$i.1 is up" | tee $tmpfile
                            else
                                 echo "172.16.$i.1 is down" | tee $tmpfile
                            fi
                                hosttmpfiles[${#hosttmpfiles[*]}]=$tmpfile
                         done
                            rm -f ${hosttmpfiles[@]}









&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

编外补充:

练习:写一个脚本,完成如下功能

(1) 提示用户输入一个可执行命令的名称;

(2) 获取此命令所依赖到的所有库文件列表;

(3) 复制命令至某目标目录(例如/mnt/sysroot,即把此目录当作根)下的对应的路径中

bash,  /bin/bash  ==> /mnt/sysroot/bin/bash

useradd, /usr/sbin/useradd  ==>  /mnt/sysroot/usr/sbin/useradd

(4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下;

/lib64/ld-linux-x8664.so.2  ==>  /mnt/sysroot/lib64/ld-linux-x8664.so.2

进一步:

每次复制完成一个命令后,不要退出,而是提示用户继续输入要复制的其它命令,并重复完成如上所描述的功能;直到用户输入“quit”退出脚本;








在bash中使用ACSII颜色

\033[31m hello \033[0m

##m:     

左侧#:

3:前景色

4:背景色

右侧#:颜色种类

1, 2, 3, 4, 5, 6, 7

#m:

加粗、闪烁等功能;

多种控制符,可组合使用,彼此间用分号隔开;

dialog命令可实现窗口化编程;

各窗体控件使用方式;

如何获取用户选择或键入的内容?

默认,其输出信息被定向到了错误输出流;

《高级bash编程指南》,《Linux命令行和shell脚本编程宝典》


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章