Linux Shell腳本編程-數組和字符串處理


數組
  1、數組的定義及聲明
  變量:存儲單個元素的內存空間
  數組:存儲多個元素的連續的內存空間,相當於多個變量的集合
  數組名:整個數組只有一個名字
  索引:編號從0開始,屬於數值索引;bash的數組支持稀疏格式(索引不連續)
  格式:
    數組名[索引]
    ${ARRAY_NAME[INDEX]} 必需用花括號{ }
    注意:索引可支持使用自定義的索引格式,而不僅僅是數值格式,即為關聯數組,bash4.0版本之后開始支持

  聲明數組:
    declare -a ARRAY_NAME:聲明一個索引數組
    declare -A ARRAY_NAME:聲明一個關聯數組(必須先聲明再使用)


  2、數組元素的賦值
  一次只賦值一個元素:
    格式:ARRAY_NAME[INDEX]=VALUE
    示例:
    weekdays[0]="Sunday"
    weekdays[4]="Thursday"

    一次賦值全部元素:
    格式:ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
    注意:可以使用命令引用,glob通配等方法賦值

  一次只賦值特定元素:(支持稀疏格式的數組)
    格式:ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)

  使用read 交互式數組賦值:
    格式:read -a ARRAY

演示:
一次只賦值一個元素:
[root@centos7 ~]# declare -a animals #使用前最好先聲明數組,當然不聲明也可以
[root@centos7 ~]# animals[0]=pig
[root@centos7 ~]# animals[1]=dog

查看賦值,一定要注意書寫格式,一定要加 {}
[root@centos7 ~]# echo $animals # 默認不加索引,顯示第0個元素
pig
[root@centos7 ~]# echo $animals[0] # 錯誤寫法,把其看做兩部分 $animals 替換為 pig,[0]隨后
pig[0]
[root@centos7 ~]# echo ${animals[0]}
pig
[root@centos7 ~]# echo ${animals[1]}
dog
[root@centos7 ~]# echo ${animals[*]} # 查看數組所有賦值
pig dog

一次賦值全部元素:
[root@centos7 ~]# number=(1 3 5 6 8 9)
[root@centos7 ~]# echo ${number[3]}
6
[root@centos7 ~]# echo ${number[0]}
1
[root@centos7 ~]# echo ${number[5]}
9
[root@centos7 ~]# echo ${number[*]}
1 3 5 6 8 9

# 下面的賦值方法也可以
[root@centos7 ~]# number=({1..9})
[root@centos7 ~]# echo ${number[*]}
1 2 3 4 5 6 7 8 9

[root@centos7 ~]# files=(/home/*)
[root@centos7 ~]# echo ${files[*]}
/home/centos /home/mage /home/mageedu

[root@centos7 ~]# files=($(ls /home)) # 命令引用 $()
[root@centos7 ~]# echo ${files[*]}
centos mage mageedu

[root@centos7 ~]# files=({1,2}{a,b}) # 命令行展開
[root@centos7 ~]# echo ${files[*]}
1a 1b 2a 2b

只賦值特定元素,稀疏格式的數組
[root@centos7 ~]# num=([0]=100 [2]=50 [3]=20)
[root@centos7 ~]# echo ${num[0]}
100
[root@centos7 ~]# echo ${num[2]}
50
[root@centos7 ~]# echo ${num[1]}

[root@centos7 ~]# echo ${num[3]}
20
[root@centos7 ~]# echo ${num[*]}
100 50 20

使用read交互式數組賦值
[root@centos7 ~]# read -a num
1 22 44 55 66 77 88 99
[root@centos7 ~]# echo ${num[0]}
1
[root@centos7 ~]# echo ${num[4]}
66
[root@centos7 ~]# echo ${num[6]}
88
[root@centos7 ~]# echo ${num[*]}
1 22 44 55 66 77 88 99

關聯數組賦值
# 使用自定義的索引格式,即關聯數組,如果不事先聲明,會出現如下錯誤,索引總是顯示最后一個元素
[root@centos7 ~]# username[F]=tao
[root@centos7 ~]# username[M]=xiu
[root@centos7 ~]# username[J]=jing
[root@centos7 ~]# echo ${username[F]}
jing
[root@centos7 ~]# echo ${username[M]}
jing
[root@centos7 ~]# echo ${username[J]}
jing
[root@centos7 ~]# echo ${username[*]}
jing

# 已經為索引數組就不能再次聲明為關聯數組了
[root@centos7 ~]# declare -A username
-bash: declare: username: 無法將索引數組轉化為關聯數組

# 聲明一個關聯數組,並賦值
[root@centos7 ~]# declare -A jianghu
[root@centos7 ~]# jianghu[A]=linghuchong
[root@centos7 ~]# jianghu[D]=qiaofeng
[root@centos7 ~]# jianghu[G]=yangguo

[root@centos7 ~]# echo "${jianghu[A]}"
linghuchong
[root@centos7 ~]# echo ${jianghu[D]}
qiaofeng
[root@centos7 ~]# echo ${jianghu[G]}
yangguo
[root@centos7 ~]# echo ${jianghu[*]}
linghuchong qiaofeng yangguo

  3、引用數組元素
  引用數組中的元素:
  格式:${ARRAY_NAME[INDEX]}
  注意:省略[INDEX]表示引用下標為0的元素;
  索引數組是從0開始索引的,如果數組元素個數為n,那么索引數為 n-1

  數組的長度:(數組中元素的個數):
  格式:
   ${#ARRAY_NAME[*]}
    ${#ARRAY_NAME[@]}

  引用數組中的所有元素:
  格式:
    ${ARRAY_NAME[*]}
    ${ARRAY_NAME[@]}

  列出數組中的所有索引:
  格式:
   ${!ARRAY_NAME[*]}
   ${!ARRAY_NAME[@]}

演示:
[root@centos7 ~]# num=({1..9})
[root@centos7 ~]# echo ${#num[*]}
9

[root@centos7 ~]# echo ${num[*]}
1 2 3 4 5 6 7 8 9
[root@centos7 ~]# echo ${num[@]}
1 2 3 4 5 6 7 8 9

[root@centos7 ~]# var=(taotao jing xiu)
[root@centos7 ~]# echo ${#var[*]}
3
[root@centos7 ~]# echo ${var[*]}
taotao jing xiu

# {}里面是一個變量,${#VAR}就表示變量的長度,而之前的$#,表示傳遞給腳本的參數個數,注意區別
# 數組中單個元素的長度
[root@centos7 ~]# echo ${#var}
6
[root@centos7 ~]# echo ${#var[2]}
3
[root@centos7 ~]# echo ${#var[1]}
4

  4、數組元素切片
  格式:${ARRAY_NAME[@]:offest:number}
  offest:要跳過的元素個數,即偏移量
  number:要取出的元素個數;省略number時,表示取偏移量之后的所有元素

演示:
[root@centos7 ~]# ls -d /etc/[Pp]*
/etc/pam.d /etc/php.d /etc/php.ini /etc/pki /etc/polkit-1 /etc/ppp /etc/profile /etc/pulse
/etc/passwd /etc/php-fpm.conf /etc/pinforc /etc/plymouth /etc/popt.d /etc/prelink.conf.d /etc/profile.d /etc/python
/etc/passwd- /etc/php-fpm.d /etc/pkcs11 /etc/pm /etc/postfix /etc/printcap /etc/protocols

# 一次賦值數組全部元素
[root@centos7 ~]# files=(/etc/[Pp]*)

[root@centos7 ~]# echo ${files[*]}
/etc/pam.d /etc/passwd /etc/passwd- /etc/php.d /etc/php-fpm.conf /etc/php-fpm.d
/etc/php.ini /etc/pinforc /etc/pkcs11 /etc/pki /etc/plymouth /etc/pm /etc/polkit-1
/etc/popt.d /etc/postfix /etc/ppp /etc/prelink.conf.d /etc/printcap /etc/profile
/etc/profile.d /etc/protocols /etc/pulse /etc/python

[root@centos7 ~]# echo ${#files[*]}
23

# 跳過前兩個元素,取后面的三個元素
[root@centos7 ~]# echo ${files[@]:2:3}
/etc/passwd- /etc/php.d /etc/php-fpm.conf

# 跳過前20個元素,取后面的所有元素
[root@centos7 ~]# echo ${files[@]:20}
/etc/protocols /etc/pulse /etc/python

  5、數組的其它用法
  向非稀疏格式數組中追加元素(先通過${#ARRAY_NAME[*]}得到當前數組的長度,以長度數字作為索引號賦值)
  ARRAY_NAEM[${#ARRAY_NAME[*]}]=
  刪除數組中的某元素
  unset ARRAY[INDEX]

  關聯數組
    首先一定要聲明數組(-A表示聲明關聯數組)
    declare -A ARRAY_NAME
    賦值
    ARRAY_NAME=([index_name1]="value1" [index_name2]="value2"...)

練習:生成10個隨機數保存於數組中,並找出其最大值和最小值
[root@centos7 bin]# cat shuzu.sh
#!/bin/bash

declare -a rand
declare -i max=0
declare -i min=0

#思路:剛生成的第一個數同時賦值給最大和最小值,然后和后面生成的隨機數作比較,如果大於最大值
# 就賦值給 max,如果小於 min 就賦值給 min

for i in {0..9};do
  rand[$i]=$RANDOM
  echo ${rand[$i]}
  if [ $i -eq 0 ];then
    max=${rand[$i]}
    min=${rand[$i]}
  elif [ ${rand[$i]} -gt $max ];then
    max=${rand[$i]}
  elif [ ${rand[$i]} -lt $min ];then
    min=${rand[$i]}
  fi
done

echo "MAX=$max"
echo "MIN=$min"

#==========================================================
[root@centos7 bin]# bash shuzu.sh
31054
4869
13722
9142
8027
16340
11938
10497
11232
13826
MAX=31054
MIN=4869

練習:寫一個腳本,定義一個數組,數組中的元素是/var/log目錄下所有以.log結尾的文件;要統計其下標為偶數的文件中的行數之和。
#!/bin/bash
#

declare -a files

files=(/var/log/*.log)

for i in $(seq 0 $[${#files[*]}-1]);do
  if [ $[$i%2] -eq 0 ];then
    lines=$(wc -l ${files[$i]} |cut -d" " -f1) # 取文件行數
    sumlines=$[$sumlines+$lines] # 總行數
  fi
done

echo "行數之和為:$sumlines"

bash的內置字符串處理工具
  字符串切片
  ${#var}        返回字符串變量var(是一個變量名)的長度
  ${var:offset}    返回字符串變量var中從第offset個字符后(不包括第offset個字符)的字符開始,到最后的部分,offset的取值在0到${#var}-1 之間
  ${var:offset:number} 返回字符串變量var中從第offset個字符后(不包括第offset個字符)的字符開始,長度為number的部分
  ${var: -lengh}    取字符串的最右側幾個字符;注意:冒號后必須有一空白字符

演示:
[root@centos7 ~]# name=guojing
[root@centos7 ~]# echo ${name}
guojing

# 查看字符串變量的長度
[root@centos7 ~]# echo ${#name}
7

# 跳過指定的偏移量,取后面的所有字符
[root@centos7 ~]# echo ${name:2}
ojing
[root@centos7 ~]# echo ${name:3}
jing

# 跳過指定的偏移量,取指定長度的字符
[root@centos7 ~]# echo ${name:2:3}
oji
[root@centos7 ~]# echo ${name:3:3}
jin

#取字符串最右側的指定長度字符
[root@centos7 ~]# echo ${name: -4}
jing
[root@centos7 ~]# echo ${name: -3}
ing

  基於模式取子串
  ${var#*pattern}  查找var所表示的字符串中,刪除自左而右第一次被pattern所匹配到的字符串及前面的所有字符串
  ${var##*pattern}  查找var所表示的字符串中,刪除自左而右最后一次被pattern所匹配到的字符串及前面的所有字符串
  ${var%pattern*}  查找var所表示的字符串中,刪除自右而左第一次被pattern所匹配到的字符串及后面的所有字符串
  ${var%%pattern*} 查找var所表示的字符串中,刪除自右而左最后一次被pattern所匹配到的字符串及后面的所有字符串

演示:
[root@centos7 ~]# mypath="/etc/init.d/functions"

# 自左而右查找由word指定的任意字符,並刪除
[root@centos7 ~]# echo ${mypath}
/etc/init.d/functions

[root@centos7 ~]# echo ${mypath#*/}
etc/init.d/functions

[root@centos7 ~]# echo ${mypath##*/}
functions

#==================================================================

# 自右而左查找由word指定的任意字符,並刪除
[root@centos7 ~]# echo ${mypath%/*}
/etc/init.d

[root@centos7 ~]# echo ${mypath%%/*} # 因為最后一個為 路徑首部的/所以全都刪除了


[root@centos7 ~]# url=http://www.magedu.com:80

[root@centos7 ~]# echo ${url##*/} # 自左而右查找最后一次出現“/”的字符,並刪除之間所有的
www.magedu.com:80

[root@centos7 ~]# echo ${url%%:*} # 自右而左查找最后一次出現“:”的字符,並刪除之間所有的
http

[root@centos7 ~]# echo ${url##*:} # 自左而右查找最后一次出現“:”的字符,並刪除之間所有的,實為取端口號
80

  字符串查找替換
  ${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風格的通配符

演示:
[root@centos7 ~]# userinfo="root:x:0:0:root admin:/root:/bin/chroot"

[root@centos7 ~]# echo ${userinfo/root/ROOT}
ROOT:x:0:0:root admin:/root:/bin/chroot

[root@centos7 ~]# echo ${userinfo/r..t/ROOT} # 不支持使用正則表達式的模式匹配
root:x:0:0:root admin:/root:/bin/chroot

root@centos7 ~]# echo ${userinfo/r??t/ROOT} # 支持 glob 風格的模式匹配
ROOT:x:0:0:root admin:/root:/bin/chroot

[root@centos7 ~]# echo ${userinfo//root/ROOT} #查找所有能夠被root匹配到的字符串,並替換為ROOT
ROOT:x:0:0:ROOT admin:/ROOT:/bin/chROOT

[root@centos7 ~]# echo ${userinfo//r??t/ROOT}
ROOT:x:0:0:ROOT admin:/ROOT:/bin/chROOT

[root@centos7 ~]# echo ${userinfo/#r??t/ROOT} # 查找行首能夠被r??t匹配到的字符串,並替換為ROOT
ROOT:x:0:0:root admin:/root:/bin/chroot

[root@centos7 ~]# echo ${userinfo/%r??t/ROOT} # 查找行尾能夠被r??t匹配到的字符串,並替換為ROOT
root:x:0:0:root admin:/root:/bin/chROOT

  字符串查找並刪除
  ${var/pattern}  查找var所表示的字符串中,刪除第一次被pattern所匹配到的字符串;
  ${var//pattern}  查找var所表示的字符串中,刪除所有被pattern所匹配到的字符串;
  ${var/#pattern} 查找var所表示的字符串中,刪除行首被pattern所匹配到的字符串;
  ${var/%pattern} 查找var所表示的字符串中,刪除行尾被pattern所匹配到的字符串;

演示:
[root@centos7 ~]# echo ${userinfo}
root:x:0:0:root admin:/root:/bin/chroot

[root@centos7 ~]# echo ${userinfo/r??t} # 刪除第一次被pattern所匹配到的字符串
:x:0:0:root admin:/root:/bin/chroot

[root@centos7 ~]# echo ${userinfo//r??t} # 刪除所有被pattern所匹配到的字符串;
:x:0:0: admin:/:/bin/ch

[root@centos7 ~]# echo ${userinfo/#r??t} # 刪除行首被pattern所匹配到的字符串;
:x:0:0:root admin:/root:/bin/chroot

[root@centos7 ~]# echo ${userinfo/%r??t} # 刪除行尾被pattern所匹配到的字符串;
root:x:0:0:root admin:/root:/bin/ch

  字符大小寫轉換
  ${var^^}  把var中的所有小寫字母轉換為大寫
  ${var,,}  把var中的所有大寫字母轉換為小寫

演示:
[root@centos7 ~]# echo $url
http://www.magedu.com:80

[root@centos7 ~]# echo ${url^^} # 小寫轉換為大寫
HTTP://WWW.MAGEDU.COM:80

[root@centos7 ~]# myurl=${url^^}

[root@centos7 ~]# echo $myurl
HTTP://WWW.MAGEDU.COM:80

[root@centos7 ~]# echo ${myurl,,} # 大寫轉換為小寫
http://www.magedu.com:80

  變量賦值
  ${varible:-default} 如果variable沒有聲明或者為空,則返回default字串;如果variable有值,則返回variable自身的值
  ${varible:+default} 如果variable沒有聲明或者為空,則返回空字串;如果variable有值,則返回default字串
  ${varible:=default} 如果variable沒有聲明或者為空,則返回default字串,並且將default賦值給variable;如果variable有值,則返回variable自身值
  ${varible:?default} 如果variable沒有聲明或者為空,則以default為錯誤信息返回;如果variable有值,則返回variable自身的值

變量測試與替換:用來判斷x的值,y是否有值  

演示:
[root@centos7 ~]# echo $hi # 變量 hi 為空

[root@centos7 ~]# echo ${hi:-world} # 如果為空或未設置,那么返回word
world
[root@centos7 ~]# echo ${hi} # 但是並沒有賦值給變量 hi

[root@centos7 ~]# hi=china # 現在賦值給變量 hi
[root@centos7 ~]# echo ${hi:-world} # 有值,則返回hi的變量值
china
[root@centos7 ~]# unset hi # 撤銷變量
[root@centos7 ~]# echo ${hi}

#==========================================================
[root@centos7 ~]# echo ${hi:=world} #為空或未設置,那么返回world,並將world賦值給hi
world
[root@centos7 ~]# echo ${hi}
world


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM