數組所謂數組,是有序的元素序列。若將有限個類型相同的變量的集合命名,那麼這個名稱爲數組名。組成數組的各個變量稱爲數組的份量,也稱爲數組的元素,有時也稱爲下標變量。用於區分數組的各個元素的數字編號稱爲下標。數組是在程序設計中,爲了處理方便, 把具備相同類型的若干元素按無序的形式組織起來的一種形式。 這些無序排列的同類數據元素的集合稱爲數組。python
變量:存儲單個元素的內存空間 ;
linux
數組:存儲多個元素的連續的內存空間,至關於多個變量的 集合
git
數組名和索引:索引:編號從0開始,屬於數值索。注意:索引可支持使用自定義的格式,而不只是數值格式 ,即爲關聯索引,bash4.0版本以後開始支持 。bash的數組支持稀疏格式(索引不連續)web
聲明數組: declare -a ARRAY_NAME
shell
declare -A ARRAY_NAME: 關聯數組
centos
注意:二者不可相互轉換數組
declare命令用於聲明和顯示已存在的shell變量。bash
declare -x varname 設置環境變量
declare -i 聲明整數
declare -g 設置函數爲全局函數
declare -xf 設置環境函數
declare -a 數組名 聲明索引數組
declare -A 數組名 聲明關聯數組
declare -a 查看全部索引數組
declare -A 查看全部關係數組服務器
數組元素的賦值oracle
(1) 一次只賦值一個元素 ARRAY_NAME[INDEX]=VALUE
weekdays[0]="Sunday"
weekdays[4]="Thursday"
[root@centos7 ~]# title[0]=boss [root@centos7 ~]# title[1]=ceo [root@centos7 ~]# title[2]=coo [root@centos7 ~]# declare -a |grep title declare -a title='([0]="boss" [1]="ceo" [2]="coo")'
(2) 一次賦值所有元素 ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
[root@centos7 ~]# name=(liubei guanyu zhangfei zhaoyun) [root@centos7 ~]# declare -a |grep name declare -a name='([0]="liubei" [1]="guanyu" [2]="zhangfei" [3]="zhaoyun")'
(3) 只賦值特定元素 ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
[root@centos7 ~]# course=([0]=linux [2]=python [5]=oracle) [root@centos7 ~]# declare -a |grep course declare -a course='([0]="linux" [2]="python" [5]="oracle")'
(4) 交互式數組值對賦值 read -a ARRAY
[root@centos7 ~]# read -a menu niuroumian caomian jidanmian [root@centos7 ~]# declare -a |grep menu declare -a menu='([0]="牛niuroumian" [1]="caomian" [2]="jidanmian")'
可使用步進
[root@centos7 ~]# digit=({1..10}) [root@centos7 ~]# declare -a |grep digit declare -a digit='([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="7" [7]="8" [8]="9" [9]="10"
可使用通配符
root@(6-1)zuoye# ser=(./*.sh root@(6-1)zuoye# declare -a |grep ser declare -a ser='([0]="./10.sh" [1]="./11.sh" [2]="./1.sh" [3]="./2.sh" [4]="./4.sh" [5]="./5.sh" [6]="./7.sh" [7]="./8.sh" [8]="./caipiao.sh" [9]="./dengyao-sjx.sh.sh" [10]="./hans.sh" [11]="./juxing.sh" [12]="./qipan.sh" [13]="./shuzi-sjx.sh" [14]="./suiji1.sh" [15]="./until.sh")'
顯示全部數組:declare -a (能夠配合grep一塊兒使用)
引用數組
引用數組元素:
${ARRAY_NAME[INDEX]}
注意:省略[INDEX]表示引用下標爲0的元素
[root@centos7 ~]# echo $digit $數組名 #僅引用第一個值 1 [root@centos7 ~]# echo ${digit[1]} #指定下標以引用指定值 3
引用數組全部元素: 數組後加「*」和「@」
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}
root@(6-1)zuoye# echo ${ser[*]} ./10.sh ./11.sh ./1.sh ./2.sh ./4.sh ./5.sh ./7.sh ./8.sh ./caipiao.sh ./dengyao-sjx.sh.sh ./hans.sh ./juxing.sh ./qipan.sh ./shuzi-sjx.sh ./suiji1.sh ./until.sh root@(6-1)zuoye# echo ${ser[@]} ./10.sh ./11.sh ./1.sh ./2.sh ./4.sh ./5.sh ./7.sh ./8.sh ./caipiao.sh ./dengyao-sjx.sh.sh ./hans.sh ./juxing.sh ./qipan.sh ./shuzi-sjx.sh ./suiji1.sh ./until.sh
數組的長度(數組中元素的個數):數組前加「#」
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
root@(6-1)zuoye# echo ${#ser[@]} 16 root@(6-1)zuoye# echo ${#ser[*]} 16
引用最後一個值
${ARRAY_NAME[$[${#ARRAY_NAME[@]}-1]]}
root@(6-1)zuoye# echo ${ser[$[${#ser[@]}-1]]} ./until.sh
練習:分別顯示每個值,每一個值換一行。
如
[root@centos7 ~]# echo ${test[@]}
hello hi good morning
test[0] is hello
test[1] is hi
test[2] is good
test[3] is morning
方式一: #在終端輸入,同bash中 [root@centos7 ~]# for n in $(seq 0 $[${#testshuzu[*]}-1]);do > echo testshuzu[$n] is ${testshuzu[$n]} > done testshuzu[0] is liubei testshuzu[1] is guanyu testshuzu[2] is zhaofei testshuzu[3] is huangzhong testshuzu[4] is zhaoyun 方式二: #在腳本中編輯, 須要重新定義數組, #!/bin/bash ser=({1..10}) #重新定義一個數組 declare -a | grep ser #輸出數組中的變量值 or i in $(seq 0 $[${#ser[@]}-1] ) ;do #取出 變量最後一個值,進行循環。 echo "ser [$i] is ${ser[$i]}" done 方式二的輸出: root@(6-1)zuoye# ./lin declare -a ser='([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="7" [7]="8" [8]="9" [9]="10")' ser [0] is 1 ser [1] is 2 ser [2] is 3 ser [3] is 4 ser [4] is 5 ser [5] is 6 ser [6] is 7 ser [7] is 8 ser [8] is 9 ser [9] is 10
在索引數組中加值,加到最後(最後一個值爲n-1,加一個值就是n-1+1,就等於n)
在索引數組中加值,加到最後 [root@centos7 ~]# testshuzu[${#testshuzu[*]}]=machao [root@centos7 ~]# for n in $(seq 0 $[${#testshuzu[*]}-1]);do echo testshuzu[$n] is ${testshuzu[$n]}; done testshuzu[0] is liubei testshuzu[1] is guanyu testshuzu[2] is zhaofei testshuzu[3] is huangzhong testshuzu[4] is zhaoyun testshuzu[5] is machao
刪除數組中的某元素:致使稀疏格式
unset ARRAY[INDEX]
root@(6-1)zuoye# unset ser[0] root@(6-1)zuoye# declare -a |grep ser declare -a ser='([1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="7" [7]="8" [8]="9" [9]="10") #顯示結果只少了ser[0]
刪除整個數組:
unset ARRAY
root@(6-1)zuoye# unset ser root@(6-1)zuoye# declare -a |grep ser root@(6-1)zuoye# #數組整個刪除沒事顯示
數組數據處理
引用數組中的元素:
數組切片:${ARRAY[@]:offset:number}
offset: 要跳過的元素個數
number: 要取出的元素個數
取偏移量以後的全部元素
${ARRAY[@]:offset}
[root@centos7 ~]# echo ${testshuzu[*]:1:3} zhaofei weiyan zhaoyun [root@centos7 ~]# echo ${testshuzu[*]:1} 跳過一個值,取到最後 zhaofei weiyan zhaoyun machao machao
向數組中追加元素:
ARRAY[${#ARRAY[*]}]=value
關聯數組:
兩種方式:
一:先聲明,再賦值
declare -A ARRAY_NAME
declare -A testshuzu testshuzu=([zhugong]=liubei [erdi]=guanyu [sandi]=zhangfei)
二:聲明,賦值一步到位
ARRAY_NAME=([idx_name1]='val1' [idx_name2]='val2‘...)
declare -A weiguo=([chengxiang]=caocao [junshi]=simayi [jiangju]=xiahoudun )
注意:關聯數組必須先聲明再調用
寫一個腳本會生成一個名爲digit的數組包含10個隨機數,顯示數組的全部值,再顯示最大值,最小值。
$RANDOM 0-32767
./digit.sh
All digit are .....
Max is
Min is
方法1: fun1() { for (( i=0;i<10;i++ ));do a=$(echo $RANDOM) digit[$i]=$a echo ${digit[$i]} done } fun1 |sort -nr > /app/shuzul cat /app/shuzul m=$( cat /app/shuzul |head -1) n=$( cat /app/shuzul |tail -1) echo max=$m echo min=$n rm /app/shuzul -rf 方法2: #!/bin/bash declare -i min max declare -a digit for ((i=0;i<10;i++));do digit[$i]=$RANDOM [ $i -eq 0 ] && min=${digit[0]} && max=${digit[0]} && continue [ ${digit[$i]} -gt $max ] && max=${digit[$i]} && continue [ ${digit[$i]} -lt $min ] && min=${digit[$i]} && continue done echo All digit are ${digit[*]} echo Max is $max echo Min is $min
編寫腳本,定義一個數組,數組中的元素是/var/log目錄下全部以.log結尾的文件;統計出其下標爲偶數的文件中的行數之和
方法1: #!/bin/bash Sum=0 File=(/var/log/*.log) for ((i=0;i<=$[${#File[*]}-1];i++));do if [ $[$i%2] -eq 0 ];then Line=$(cat ${File[$i]} | wc -l) Sum=$[$Sum+$Line] fi done echo $Sum 方法2: declare -a logfiles=(/var/log/*.log) echo All logfile name ${logfiles[*]} i=0 linesum=0 while [ $i -lt ${#logfiles[*]} ];do [ $[i%2] -eq 0 ]&& fileline=$(cat ${logfiles[$i]} |wc -l ) && let linesum+=$fileline let i++ done echo All lines are $linesum
字符串字符串切片
${#var}:返回字符串變量var的長度
echo ${#name} echo ${#name[1]} 顯示變量或數組的字符數
root@(6-1)zuoye# name=wang123 root@(6-1)zuoye# echo ${#name} 7 root@(6-1)zuoye# echo ${#name[1]} 0 root@(6-1)zuoye# echo $name wang123
${var:offset}:返回字符串變量var中從第offset個字符後(不包括 第offset個字符)的字符開始,到最後的部分,offset的取值在0 到 ${#var}-1 之間(bash4.2後,容許爲負值)
root@(6-1)zuoye# echo ${name:2} #從左邊跳過2個字符,取到最後 ng123
${var:offset:number}:返回字符串變量var中從第offset個字符後 (不包括第offset個字符)的字符開始,長度爲number的部分
root@(6-1)zuoye# echo ${name:2:3} #從左邊跳過2個字符,取3個字符 ng1
${var: -length}:取字符串的最右側幾個字符
root@(6-1)zuoye# echo ${name: -2} #從右向左取2個字符,注意冒號後至少打一個空格 23 注意:冒號後必須有一空白字符
${var:offset:-length}:從最左側跳過offset字符,一直向右取到 距離最右側lengh個字符以前的內容
[root@centos7 ~]# echo ${name:3:-1} #從左邊跳過3個字符,從右邊跳過1個字符 r1 root@(6-1)zuoye# echo ${name: -3:1} #從右向左取3個字符,再從左向右取1個字符 1
${var: -length:-offset}:先從最右側向左取到length個字符開始 ,再向右取到距離最右側offset個字符之間的內容
name=qwer12 root@(6-1)zuoye# echo ${name:-3:-1} #從右向左取3個字符,再從右向左去掉1個字符 r1 注意:-length前空格
字符串處理
基於模式取子串
${var#*word}:其中word能夠是指定的任意字符 功能:自左而右,查找var變量所存儲的字符串中,第一 次出現的word, 刪除字符串開頭至第一次出現word字符之間的 全部字符
從左至右查找 [root@centos7 ~]# echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin [root@centos7 ~]# echo ${PATH#*local} /sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
${var##*word}:同上,貪婪模式,不一樣的是,刪除的 是字符串開頭至最後一次由word指定的字符之間的全部內容
示例:
file="var/log/messages「
${file#*/}: log/messages
${file##*/}: messages
[root@centos7 ~]# echo ${PATH##*local} 貪婪模式 /bin:/usr/sbin:/usr/bin:/root/bin
${var%word*}:其中word能夠是指定的任意字符;
功能:自右而左,查找var變量所存儲的字符串中,第一 次出現的word, 刪除字符串最後一個字符向左至第一次出現 word字符之間的全部字符;
file="/var/log/messages"
${file%/*}: /var/log
從左至右查找 [root@centos7 ~]# echo ${PATH} /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin [root@centos7 ~]# echo ${PATH%local*} /usr/local/sbin:/usr/
${var%%word*}:同上,只不過刪除字符串最右側的字符向 左至最後一次出現word字符之間的全部字符;
[root@centos7 ~]# echo ${PATH%%local*} /usr/ [root@centos7 ~]# url=http://www.magedu.com:8080 [root@centos7 ~]# echo ${url%%:*} http [root@centos7 ~]# echo ${url##*:} 8080
[root@centos7 ~]# url=http://www.magedu.com:8080 [root@centos7 ~]# echo ${url%%:*} http [root@centos7 ~]# echo ${url##*:} 8080
示例:
${url##*:} 80
${url%%:*} http
查找替換
${var/pattern/substr}:查找var所表示的字符串中,第 一次被pattern所匹配到的字符串,以substr替換之
${var//pattern/substr}: 查找var所表示的字符串中, 全部能被pattern所匹配到的字符串,以substr替換之
${var/#pattern/substr}:查找var所表示的字符串中, 行首被pattern所匹配到的字符串,以substr替換之
${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中的全部大寫字母轉換爲小寫
[root@centos7 ~]# name="Zhangfei LiuBeI" [root@centos7 ~]# echo ${name,,} zhangfei liubei [root@centos7 ~]# echo ${name^^} ZHANGFEI LIUBEI
高級變量用法-有類型變量
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@centos7 ~]# mage=linux [root@centos7 ~]# linux=centos [root@centos7 ~]# eval echo \$$mage centos [root@centos7 ~]# centos=redhat [root@centos7 ~]# eval echo \$$(eval echo \$$mage) redhat [root@centos7 ~]# n=10 [root@centos7 ~]# echo {1..$n} {1..10} [root@centos7 ~]# eval echo {1..$n} 1 2 3 4 5 6 7 8 9 10
間接變量引用
若是第一個變量的值是第二個變量的名字,從第一個變量引 用第二個變量的值就稱爲間接變量引用
variable1的值是variable2,而variable2又是變量名, variable2的值爲value,間接變量引用是指經過variable1獲 得變量值value的行爲
variable1=variable2
variable2=value
bash Shell提供了兩種格式實現間接變量引用
eval tempvar=\$$variable1
tempvar=${!variable1}
[root@centos7 ~]# echo $mage linux [root@centos7 ~]# echo $linux centos [root@centos7 ~]# test=${!mage} [root@centos7 ~]# echo $test centos
建立臨時文件
mktemp命令:建立並顯示臨時文件,可避免衝突
mktemp [OPTION]... [TEMPLATE]
TEMPLATE: filename.XXX
X至少要出現三個
OPTION:
-d: 建立臨時目錄
-p DIR或--tmpdir=DIR:指明臨時文件所存放目錄位置
示例:
mktemp /tmp/test.XXX tmpdir=`mktemp –d /tmp/testdir.XXX` 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
示例:
install -m 700 -o wang -g admins srcfile desfile install –m –d /testdir/installdir install -m 700 -o liubei -g root /etc/passwd /app/hellopasswd
expect介紹
expect 是由Don Libes基於Tcl( Tool Command Language )語言開發的,主要應用於自動化交互式操做的場景,藉助 Expect處理交互的命令,能夠將交互過程如:ssh登陸,ftp 登陸等寫在一個腳本上,使之自動化完成。尤爲適用於須要 對多臺服務器執行相同操做的環境中,能夠大大提升系統管 理人員的工做效率
expect命令
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最經常使用的語法(tcl語言:模式-動做)
單一分支模式語法:
expect "hi" {send "You said hi\n"}
root@(6-1)~# expect #進入expect交互式模式
expect1.3> expect "hi" {send "You said hi\n"} # expect 從進程接收字符串 , send:用於向進程發送字符串 ,
hi
You said hi
匹配到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 #time:2018.3.24 #edition:1.1 #effect:Interactive logon automatic input password(交互式登陸自動輸入密碼) #expect格式開頭 #spawn新建進程,也就是ssh的鏈接 spawn ssh root@172.18.250.249 #expect 從進程接收字符串 ,設置接收字符串 #send 向進程發送字符串,設置密碼... #exp_continue,須要匹配的次數不止一次,因此須要在前邊, #執行動做後加上exp_continue,以表示還有,後邊還有動做,沒有結束. expect { "yes/no" { send "yes\n" ;exp_continue } "password" { send "centos\n" } } #interact容許用戶交互,不管值執不執行腳本任務,最後停留在目標終端上。 interact #expect eof表示結束,登錄上去執行完腳本任務,直接退出,不在目標終端上停留 #expect eof ~
方式二:
設置變量方式實現
#!/usr/bin/expect #time:2018.3.24 #edition:1.1 #effect:Interactive logon automatic input password(交互式登陸自動輸入密碼) #設置三個變量 set user root set remotehost 172.18.250.249 set password centos spawn ssh $user@$remotehost expect { "yes/no" { send "yes\n" ;exp_continue } "password" { send "$password\n" } } interact #expect eof
方法三:
執行登陸後的後續操做
設置三個位置變量來實現變量的賦值
#!/usr/bin/expect #time:2018.3.24 #edition:1.1 #effect:Interactive logon automatic input password(交互式登陸自動輸入密碼) #設置三個位置變量 set user [lindex $argv 0] set remotehost [lindex $argv 1] set password [lindex $argv 2] spawn ssh $user@$remotehost expect { "yes/no" { send "yes\n" ;exp_continue } "password" { send "$password\n" } } expect "]#" { send "useradd liubei\n" } expect "]#" { send "echo redhat|passwd --stdin liubei\n" } send "exit\n" expect eof
方法四:
使用shell腳本格式
經過EOF實現賦值。
#!/bin/bash #time:2018.3.24 #edition:1.1 #effect:Interactive logon automatic input password(交互式登陸自動輸入密碼) user=$1 remotehost=$2 password=$3 expect << EOF spawn ssh $user@$remotehost expect { "yes/no" { send "yes\n" ;exp_continue } "password" { send "$password\n" } } expect "]#" { send "useradd liubei\n" } expect "]#" { send "echo redhat|passwd --stdin liubei\n" } send "exit\n" expect eof EOF
精簡的shell
#!/bin/bash #time:2018.3.24 #edition:1.1 #effect:Interactive logon automatic input password(交互式登陸自動輸入密碼) user=$1 remotehost=$2 password=$3 expect << EOF spawn ssh $user@$remotehost expect { "yes/no" { send "yes\n" ;exp_continue } "password" { send "$password\n" } } expect "]#" { send "useradd liubei\n" } expect "]#" { send "id liubei" } interact EOF