系統基礎之shell腳本編程詳解4(數組及字符串處理,變量賦值和配置文件)
今天來講shell腳本編程的最后一些內容,數組及字符串處理,變量賦值和配置文件.這些內容也是我們經常在工作中使用到的知識點.下面讓我們來詳細了解下:
數組:
程序=指令+數據
指令:編程語法的關鍵字,調用系統命令,編寫的函數
數據:變量,文件
變量:存儲單個元素的內存空間;
數組:存儲多個元素的連續的內存空間;(連續的內存空間存儲連續的元素,元素有獨立的空間,但只有一個統一的名字,索引表示各個元素)
數組名:整個數組只有一個名字;數組的標識,數組名指向的存儲多個元素的內存空間起始地址的標識
數組索引:編號從0開始,1,2,3..N
使用方式:數組名[索引]
${ARRAY_NAME[INDEX]}
注意:bash-4及以后的版本,支持自定義索引格式,而不僅僅是0,1,2..數字格式;
此類數組稱之為"關聯數組"
聲明數組:
declare -a name: 聲明索引數組
declare -A name: 聲明關聯數組(自定義下標的數組,必須聲明)
也可不聲明,直接使用
animals[0]=pig
animals[1]=dog
引用數組:
1.直接引用數組名,顯示第一個數組的元素. echo $animals
2.指定引用元素:
數組的賦值方式:
1.一次只復制一個元素
ARRAY_name[IDX]=value
2.一次復制全部元素
ARRAY_name=("mem" "TUS" "web")
3.只賦值特定元素:
ARRAY_name=([0]="mem" [3]="erv"..)
注意:bahs支持稀疏格式的數組
4.read -a ARRAY_NAME
[root@wen-7 shangkelianxi]# qwe=(1 2 4 5 67 8 9 ) [root@wen-7 shangkelianxi]# qwe[1]=1 [root@wen-7 shangkelianxi]# qwe=([1]=1 [2=]2 ) [root@wen-7 shangkelianxi]# read -a qwe 1 2 3 4 5
引用數組中的元素,${ARRAY_NAME[INDEX]}
注意:引用時,只給數組名,表示引用下標為0的元素;
[root@wen-7 shangkelianxi]# echo ${qwe[1]} 2 [root@wen-7 shangkelianxi]# echo ${qwe[2]} 3 [root@wen-7 shangkelianxi]# echo ${qwe} 1
數組的長度(數組中元素的個數)
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
[root@wen-7 shangkelianxi]# echo ${#qwe[@]} 5 [root@wen-7 shangkelianxi]# echo ${#qwe[*]} 5
引用數組中所有元素:
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}
[root@wen-7 shangkelianxi]# echo ${qwe[*]} 1 2 3 4 5 [root@wen-7 shangkelianxi]# echo ${qwe[@]} 1 2 3 4 5
數組元素切片:$ {ARRAY_NAME[@]:offset:number}
offset:要路過的元素個數
number:要去除的元素個數,省略number時,表示取偏移量之后的所有元素
[root@wen-7 shangkelianxi]# echo ${qwe[@]:2:3} 3 4 5 [root@wen-7 shangkelianxi]# echo ${qwe[@]:2:1} 3
向非稀疏數組中追加元素:
ARRAY_name[${ARRAY_name[*]}]=
刪除數組中的元素
unset ARRAY[index]
[root@wen-7 shangkelianxi]# unset qwe[2] [root@wen-7 shangkelianxi]# echo ${qwe[2]}
關聯數組
declare -A ARRAY_name
ARRAY_NAME=([index_name1]="value1" [index_name1]="value2")
[root@wen-7 shangkelianxi]# declare -A asd [root@wen-7 shangkelianxi]# asd=([a]="qwe" [b]="zc" [c]="fd1") [root@wen-7 shangkelianxi]# echo ${asd[a]} qwe [root@wen-7 shangkelianxi]# echo ${asd[b]} zc
實戰:
1.生成10個隨機數,并找出其中的最大值和最小值
declare -a rand declare -i max=0 declare -i min=99999 for i in {1..9};do rand[$i]=$RANDOM echo ${rand[$i]} [ ${rand[$i]} -gt $max ] && max=${rand[$i]} [ ${rand[$i]} -lt $min ] && min=${rand[$i]} done echo "max: $max min:$min"
2.定義一個數組,數組中的元素是/var/log目錄下所有以.log結尾文件,統計其下標為偶數的文件中的行數之和
declare -a files files=(/var/log/*.log) declare -i lins=0 for i in $(seq 0 $[${#files[*]}-1]);do if [ $[$i%2] -eq 0 ]; then let lins+=$(wc -l ${files[$i]} | cut -d' ' -f1) fi done echo "lines:$lins"
3. 冒泡法,計算10個隨機數,從大到小,從小到大排列
declare -i num; read -a arg -p "請輸入10個數字:" for((i=0;i<=9;i++))do for((k=$[i+1];k<=9;k++))do if [ ${arg[$i]} -gt ${arg[$k]} ];then num=${arg[$i]} arg[$i]=${arg[$k]} arg[$k]=$num fi done done echo "正序排列${arg[*]}" echo "==============" for((i=0;i<=9;i++))do for((k=$[i+1];k<=9;k++))do if [ ${arg[$i]} -lt ${arg[$k]} ];then num=${arg[$i]} arg[$i]=${arg[$k]} arg[$k]=$num fi done done echo "逆序排列${arg[*]}"
字符串處理:
bash的內置字符串處理工具
字符串切片:
${var:offset:number}
取字符串的子串
[root@wen-7 shangkelianxi]# name=jerry [root@wen-7 shangkelianxi]# echo ${name:2} rry [root@wen-7 shangkelianxi]# echo ${name:2:2} rr
取字符串的最右側的幾個字符:${var: -length}
注意:冒號后必須有一個空白字符
[root@wen-7 shangkelianxi]# echo ${name: -4} erry
基于模式取子串:
${var#*word}:其中word是指定的分隔符,功能:自左而右,查找var變量所存儲的字符串中,第一次出現的word分隔符,刪除字符串開頭至此分隔符之間的所有字符.
${var##*word}:其中word是指定的分隔符,功能:自左而右,查找var變量所存儲的字符串中,最后一次出現的word分隔符,刪除字符串開頭至此分隔符之間的所有字符.
[root@wen-7 shangkelianxi]# myfa="/etc/init.d/functions" [root@wen-7 shangkelianxi]# echo ${myfa#*/} etc/init.d/functions [root@wen-7 shangkelianxi]# echo ${myfa##*/} functions
${var%word*}:其中word是指定的分隔符,功能:自右而左,查找var變量所存儲的字符串中,第一次出現的word分隔符,刪除字符串開頭至此分隔符之間的所有字符.
${var%%word*}:其中word是指定的分隔符,功能:自右而左,查找var變量所存儲的字符串中,最后一次出現的word分隔符,刪除字符串開頭至此分隔符之間的所有字符.
[root@wen-7 shangkelianxi]# myfa="/etc/init.d/functions" [root@wen-7 shangkelianxi]# echo ${myfa%/*} /etc/init.d [root@wen-7 shangkelianxi]# echo ${myfa%%/*} [root@wen-7 shangkelianxi]#mypath="/etc/init.d/funtion" ${mypath%*} /etc/init.d url=http://www.magedu.com:80 {url##*:} {url%%:*}
查找替換:
${var/PATTERN/SUBST}:查找var所代表的字符串中,第一次被PATTERN所匹配到的字符串,將其替換為SUBSTI所表示的字符串
${var//PATTERN/SUBST}:查找var所代表的字符串中,所有被PATTERN所匹配到的字符串,將其替換為SUBSTI所表示的字符串
${var/#PATTERN/SUBSTI}:查找var所代表的字符串中,行首被PATTERN所匹配到的字符串,將其替換為SUBSTI所表示的字符串
${var/%PATTERN/SUBSTI}:查找var所代表的字符串中,行尾被PATTERN所匹配到的字符串,將其替換為SUBSTI所表示的字符串
[root@wen-7 ~]# user="root:x:0:0:root admin:/root:bin/chroot" [root@wen-7 ~]# echo ${user/root/ROOT} ROOT:x:0:0:root admin:/root:bin/chroot [root@wen-7 ~]# echo ${user//root/ROOT} ROOT:x:0:0:ROOT admin:/ROOT:bin/chROOT [root@wen-7 ~]# echo ${user/#root/ROOT} ROOT:x:0:0:root admin:/root:bin/chroot [root@wen-7 ~]# echo ${user/%root/ROOT} root:x:0:0:root admin:/root:bin/chROOT 注意:PATTERN中使用glob風格的通配符
查找刪除:
${var/PATTERN}:以PATTERN為模式,查找var字符串中第一次的匹配,并刪除值
${var//PATTERN}:以PATTERN為模式,查找var字符串中所有的匹配,并刪除值
${var/#PATTERN}:以PATTERN為模式,查找var字符串中行首的匹配,并刪除值
${var/%PATTERN}:以PATTERN為模式,查找var字符串中行尾的匹配,并刪除值
[root@wen-7 shangkelianxi]# var=`getent passwd | grep ^root` [root@wen-7 shangkelianxi]# echo $var root:x:0:0:root:/root:/bin/bash [root@wen-7 shangkelianxi]# echo ${var/root} :x:0:0:root:/root:/bin/bash [root@wen-7 shangkelianxi]# echo ${var//root} :x:0:0::/:/bin/bash [root@wen-7 shangkelianxi]# echo ${var/#root} :x:0:0:root:/root:/bin/bash [root@wen-7 shangkelianxi]# echo ${var/%bash} root:x:0:0:root:/root:/bin/
字符大小寫轉換:
${var^^}:把var中的所有小寫字符轉化為大寫
${var,,}:把var中的所有大寫字符轉化為小寫
[root@wen-7 shangkelianxi]# var=dfadfkladsnfkldshfkdf [root@wen-7 shangkelianxi]# echo ${var^^} DFADFKLADSNFKLDSHFKDF [root@wen-7 shangkelianxi]# var=AJDKFDAFKLDF [root@wen-7 shangkelianxi]# echo ${var,,} ajdkfdafkldf
變量賦值及引用:
變量賦值:
${var:-value}: 如果var變量為空,或未定義,那么返回value為值,否則,則返回var變量值
[root@wen-7 ~]# echo ${user:-qwe} root:x:0:0:root admin:/root:bin/chroot [root@wen-7 ~]# unset user [root@wen-7 ~]# echo ${user:-qwe} qwe
${var:=value}如果var變量為空,或未定義,那么返回value,并將value賦值給var變量,否則,則返回var變量值
[root@wen-7 ~]# user=adfdf [root@wen-7 ~]# echo ${user:=qwe} adfdf [root@wen-7 ~]# unset user [root@wen-7 ~]# echo ${user:=qwe} qwe
${var:+value}:如果var變量不空,則返回value為值.
[root@wen-7 ~]# user=adfdf [root@wen-7 ~]# echo ${user:+qwe} qwe
${var:?ERROR_INFO}:如果var變量為空,或未定義,則返回ERROR_INFO,否則,返回var的值
[root@wen-7 ~]# user=adfdf [root@wen-7 ~]# echo ${user:?error} adfdf [root@wen-7 ~]# unset user [root@wen-7 ~]# echo ${user:?error} -bash: user: error
為腳本程序使用配置文件,實現變量賦值(編寫變亮腳本,多次引用)
(1) 定義文本文件,每行定義“ name=value”
(2) 在腳本中source此文件即可
[root@wen-7 shangkelianxi]# cat variable.sh #!/bin/bash declare -A qwe qwe=([a]="qas" [b]="zxc" ) declare -a asd asd=(1 2 3 5 4 6) declare -i sum=0 [root@wen-7 shangkelianxi]# cat variable1.sh #!/bin/bash source variable.sh echo ${qwe[a]} echo ${qwe[b]} echo $sum [root@wen-7 shangkelianxi]# bash variable1.sh qas zxc 4
變量高級用法-有類型變量
Shell變量一般是無類型的,但是bash Shell提供了declare和
typeset兩個命令用于指定變量的類型,兩個命令是完全等價的
declare [選項] 變量名
-r 將變量設置為只讀屬性
-i 將變量定義為整型數
-a 將變量定義為數組
-f 顯示此腳本前定義過的所有函數名及其內容
-F 僅顯示此腳本前定義過的所有函數名
-x 將變量聲明為環境變量
-l 將變量值轉為小寫字母
-u 將變量值轉為大寫字母
間接變量引用:
如果第一個變量的值是第二個變量的名字,從第一個變量引用第二個變量的值就稱為間接變量引用
variable1=variable2
variable2=value
variable1的值是variable2,而variable2又是變量名,
variable2的值為value,間接變量引用是指通過variable1獲得變量值value的行為
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=\$$A [root@server ~]# echo $2 wangxiaochun
eval命令:
eval命令將會首先掃描命令行進行所有的置換,然后再執行該命令。該命令適用于那些一次掃描無法實現其功能的變量。該命令對變量進行兩次掃描
[root@server ~]# V1=pwd [root@server ~]# echo $V1 pwd [root@server ~]# eval $V1 /root
創建臨時文件
mktemp命令:創建的臨時文件可避免沖突
mktemp [OPTION]… [TEMPLATE]
TEMPLATE: filename.XXX
X至少要出現三個
? OPTION:
-d: 創建臨時目錄
–tmpdir=/DIR:指明臨時文件所存放的目錄位置
#mktemp --tmpdir=/testdir test.XXXXXX
安裝復制文件
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
bash如何展開命令行
把命令行分成單個命令詞
展開別名
展開大括號種的聲明( {})
展開波浪符聲明( ~)
命令替換$() 和 “)
再次把命令行分成命令詞
展開文件通配( *、 ?、 [abc]等等)
準備I/0重導向( <、 >)
運行命令
防止擴展
反斜線( \)會使隨后的字符按原意解釋
$ echo Your cost: \$5.00
Your cost: $5.00
加引號來防止擴展
單引號( ’)防止所有擴展
雙引號( ”)也防止所有擴展,但是以下情況例外:
$(美元符號) - 變量擴展
(反引號) - 命令替換
\(反斜線) - 禁止單個字符擴展
!(嘆號) - 歷史命令替換
配置文件:
兩類:
profile類:為交互式登錄的shell進程提供配置
bashrc類:為交互式登錄的shell進程提供配置
登錄類型:
交互式登錄shell進程:
直接通過某終端輸入賬號密碼后登錄打開的shell進程
使用su命令,:su – uaername ;su -l Username 執行的登錄切換
非交互式登錄shell進程:
su username 執行的登錄切換
圖形界面下打開的終端
運行腳本
profile類:為交互式登錄的shell進程提供配置
全局:對所有用戶都生效
/etc/profile
/etc/profile.d/*.sh
局部:僅對當前用戶生效
~/.bash_profile
功用:
用于定義環境變量
運行命令或腳本
bashrc類:
全局:
/etc/bashrc
局部:僅對當前用戶生效
~/.bashrc
功用:
定義本地變量
冬衣命令別名
注意:僅管理員可修改全局配置文件
交互式登錄shell進程:
/etc/profile–>/etc/profile.d/* –>~/.bash_profile–>~/.bashrc–>/etc/bashrc
非交互式登錄shell進程:
~/.bashrc–>/etc/bashrc–>/etc/profile.d/*
命令行中定義的特性,例如變量和別名作用域為當前shell進程的生命周期;
配置文件定義的特性,只對隨后新啟動的shell進程有效。
讓通過配置文件定義的特性立即生效:
(1)用過命令重新定義一次;
(2)讓shell進程重讀配置文件
~]#source /path/TO/CONF_FILE
~]#./path/TO/CONF_FILE
問題:
1.如何定義對所有用戶都生效的命令別名
在/etc/profile.d/中編寫文件
2.讓centos用戶登錄時,提供其已登錄 并顯示當前系統時間
[root@wen-7 ~]# vim /home/centos/.bash_login echo "hello $HOSTNAME" date
原創文章,作者:wencx,如若轉載,請注明出處:http://www.www58058.com/39452