note_17.1_shell數(shù)組、bash字符串操作

shell腳本編程

變量:存儲單個元素的內(nèi)存空間;
數(shù)組:存儲多個元素的連續(xù)的內(nèi)存空間;
├── 數(shù)組名:整個數(shù)組只有一個名字;
└── 數(shù)組索引:編號從0開始;

數(shù)組名[索引],
${ARRAY_NAME[INDEX]}

數(shù)組引用必須要加上花括號

注意:bash-4及之后的版本,支持自定義索引格式,而不僅僅是0,1,2,...數(shù)字格式;
此類數(shù)組稱之為“關(guān)聯(lián)數(shù)組”

聲明數(shù)組:

├── declare -a NAME:聲明索引數(shù)組;
└── declare -A NAME:聲明關(guān)聯(lián)數(shù)組;(可以理解成key-value)

數(shù)組中元素的賦值方式:

  1. 一次只賦值一個元素;
    ARRAY_NAME[INDEX]=value
  2. 一次賦值全部元素;
    ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
  3. 只賦值特定元素;
    ARRAY_NAME=([0]="VAL1" [3]="VAL4" ...)

    注意:bash支持稀疏格式的數(shù)組;

  4. read -a ARRAY_NAME

數(shù)組的長度(數(shù)組中元素的個數(shù)):

${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}

${#ARRAY_NAME}數(shù)組第一個元素的字符數(shù)

示例:生成10個隨機數(shù),并找出其中的最大值和最小值;

[root@localhost ~]# bash /scripts/e17-1-1.sh
13621 26112 6628 32725 6633 10439 12141 11041 17213 4454
max number is : 32725
[root@localhost ~]# cat /scripts/e17-1-1.sh
#!/bin/bash

declare -a rand
declare -i max=0
for i in {1..10};do
    rand[$[$i-1]]=$RANDOM
    [ ${rand[$[$i-1]]} -gt $max ] && max=${rand[$[$i-1]]}
done
echo ${rand[*]}
echo "max number is : $max"

練習:生成10個隨機數(shù),而后由小到大進行排序;

[root@localhost ~]# bash  /scripts/e17-1-2.sh
32513 24837 22630 21323 17125 15063 7133 611 567 124
[root@localhost ~]# bash  /scripts/e17-1-2.sh
30149 28684 26592 24703 19941 18643 16756 11298 7533 2952
[root@localhost ~]# cat  /scripts/e17-1-2.sh
#!/bin/bash

declare -a sortarr
tmp=0
foo=0
bar=0
for i in {0..9};do
    sortarr[$i]=$RANDOM
done
for ((i=0 ; i<10 ; i++));do
    foo=$i
    for (( j=$[$i-1] ; j>=0 ; j-- ));do
        bar=$j
        if [ ${sortarr[$foo]} -gt ${sortarr[$bar]} ];then
            tmp=${sortarr[$foo]}
            sortarr[$foo]=${sortarr[$bar]}
            sortarr[$bar]=$tmp
            foo=$bar
        fi
    done
done
echo ${sortarr[*]}

練習:寫一個腳本

定義一個數(shù)組,數(shù)組中的元素是/var/log目錄下所有以.log結(jié)尾的文件;統(tǒng)計其下標為偶數(shù)的文件中的行數(shù)之和;

[root@localhost ~]# bash /scripts/e17-1-3.sh
579
[root@localhost ~]# cat /scripts/e17-1-3.sh
#!/bin/bash

declare -a files
files=(/var/log/*.log)
declare -i  sum=0
for i in $(seq 0 $[${#files[*]}-1]);do
    [ $[$i%2] -eq 0 ] && let sum+=`wc -l ${files[$i]} | cut -d' ' -f1`
done
echo $sum

引用數(shù)組中的所有元素:

${ARRAY_NAME[*]}
${ARRAY_NAME[@]}

數(shù)組元素切片:

${ARRAY_NAME[@]:offset:number}
├── offset:要路過的元素個數(shù);
└── number:要取出的元素個數(shù);省略number時,表示取偏移量之后的所有元素;

  • 向非稀疏格式數(shù)組中追加元素:
    ARRAY_NAME[${#ARRAY_NAME[*]}]=

  • 刪除數(shù)組中的某元素:
    unset ARRAY[INDEX]

關(guān)聯(lián)數(shù)組:

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


bash的內(nèi)置字符串處理工具:

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

取字符串的最右側(cè)的幾個字符:${var: -length}
注意:冒號后必須有一個空白字符;

  • 基于模式取子串:
    ${var#*word}:其中word是指定的分隔符;功能:自左而右,查找var變量所存儲的字符串中,第一次出現(xiàn)的word分隔符,刪除字符串開頭至此分隔符之間的所有字符;

    [root@localhost ~]# str='hello world 123'
    [root@localhost ~]# echo ${str#*world}
    123
    

    ${var##*word}:其中word是指定的分隔符;功能:自左而右,查找var變量所存儲的字符串中,最后一次出現(xiàn)的word分隔符,刪除字符串開頭至此分隔符之間的所有字符;

    mypath="/etc/init.d/functions"
    ${mypath##*/}:   functions
    ${mypath#*/}:  etc/init.d/functions
    

    ${var%word*}:其中word是指定的分隔符;功能:自右而左,查找var變量所存儲的字符串中,第一次出現(xiàn)的word分隔符,刪除此分隔符至字符串尾部之間的所有字符;
    ${var%%word*}:其中word是指定的分隔符;功能:自右而左,查找var變量所存儲的字符串中,最后一次出現(xiàn)的word分隔符,刪除此分隔符至字符串尾部之間的所有字符;

    mypath="/etc/init.d/functions"
    ${mypath%/*}:  /etc/init.d
                  
    url=http://www.magedu.com:80
    ${url##*:} :80
    ${url%%:*} : http
    
  • 查找替換:
    ${var/PATTERN/SUBSTI}:查找var所表示的字符串中,第一次被PATTERN所匹配到的字符串,將其替換為SUBSTI所表示的字符串;
    ```${var//PATTERN/SUBSTI}``:查找var所表示的字符串中,所有被PATTERN所匹配到的字符串,并將其全部替換為SUBSTI所表示的字符串;

    ${var/#PATTERN/SUBSTI}:查找var所表示的字符串中,行首被PATTERN所匹配到的字符串,將其替換為SUBSTI所表示的字符串;
    ${var/%PATTERN/SUBSTI}:查找var所表示的字符串中,行尾被PATTERN所匹配到的字符串,將其替換為SUBSTI所表示的字符串;

    注意:PATTERN中使用glob風格的通配符;

  • 查找刪除:
    ${var/PATTERN}:以PATTERN為模式查找var字符串中第一次的匹配,并刪除之;
    ${var//PATERN}:刪除全部匹配
    ${var/#PATTERN}:只刪除行首的匹配
    ${var/%PATTERN}:只刪除行尾的匹配

  • 字符大小寫轉(zhuǎn)換:
    ${var^^}:把var中的所有小寫字符轉(zhuǎn)換為大寫;
    ${var,,}:把var中的所有大寫字符轉(zhuǎn)換為小寫;

  • 變量賦值:
    ${var:-VALUE}:如果var變量為空,或未設(shè)置,那么返回VALUE;否則,則返回var變量的值;
    ${var:=VALUE}:如果var變量為空,或未設(shè)置,那么返回VALUE,并將VALUE賦值給var變量;否則,則返回var變量的值;
    ${var:+VALUE}:如果var變量不空,則返回VALUE;
    ${var:?ERROR_INFO}:如果var為空,或未設(shè)置,那么返回ERROR_INFO為錯誤提示;否則,返回var值;

練習:寫一個腳本,完成如下功能

(1) 提示用戶輸入一個可執(zhí)行命令的名稱;
(2) 獲取此命令所依賴到的所有庫文件列表;
(3) 復(fù)制命令至某目標目錄(例如/mnt/sysroot,即把此目錄當作根)下的對應(yīng)的路徑中
bash, /bin/bash ==> /mnt/sysroot/bin/bash
useradd, /usr/sbin/useradd ==> /mnt/sysroot/usr/sbin/useradd
(4) 復(fù)制此命令依賴到的所有庫文件至目標目錄下的對應(yīng)路徑下;
/lib64/ld-linux-x8664.so.2 ==> /mnt/sysroot/lib64/ld-linux-x8664.so.2

進一步:
每次復(fù)制完成一個命令后,不要退出,而是提示用戶繼續(xù)輸入要復(fù)制的其它命令,并重復(fù)完成如上所描述的功能;直到用戶輸入“quit”退出腳本;

[root@localhost ~]# bash /scripts/e17-1-4.sh
please input an excutable COMMAND :bash
please input an excutable COMMAND :quit      
[root@localhost ~]# tree /mnt/sysroot/
/mnt/sysroot/
├── lib64
│   ├── ld-linux-x86-64.so.2
│   ├── libc.so.6
│   ├── libdl.so.2
│   └── libtinfo.so.5
└── usr
    └── bin
        └── bash

3 directories, 5 files
[root@localhost ~]# cat /scripts/e17-1-4.sh
#!/bin/bash

sysroot='/mnt/sysroot'
function commv {
    declare -a sofiles
    cpath=`whereis $1 |cut -d' ' -f2`
    [[ -d "$sysroot`dirname $cpath`" ]] || mkdir -p $sysroot`dirname $cpath`
    cp $cpath $sysroot$cpath
    sofiles=(`ldd $cpath |grep -o '/\S*/\S\+'`)
    for i in ${sofiles[*]};do
        [[ -d "$sysroot`dirname $i`" ]] || mkdir -p $sysroot`dirname $i`
        cp $i $sysroot$i
    done
}
while true;do
    read -p 'please input an excutable COMMAND :' cname
    [[ $cname == 'quit' ]] && break
    commv $cname
done
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容