Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)

如何定義函數(/etc/init.d下有個系統內定functions)



function: function name { COMMANDS ; } or name () { COMMANDS ; }

Define shell function.

Create a shell function named NAME.  When invoked as a simple command,
NAME runs COMMANDs in the calling shell's context.  When NAME is invoked,
the arguments are passed to the function as $1...$n, and the function's
name is in $FUNCNAME.

Exit Status:
Returns success unless NAME is readonly.

語法一:
f_name (){
...函數體...
}
語法二:
function f_name {
...函數體...
}
語法三:
function f_name () {
...函數體...
}

定義函數和調用函數
單獨寫一個腳本functions,內部定義需要用到的函數,用的時候直接在新的shell中source functions。

示例
functions
func1 () {
echo func1
local name=mage----------》函數內的變量儘量定義成本地變量,防止腳本調用該函數時,腳本內有變量名稱和函數內的變量名稱一樣,造成變量污染
return 10---------》返回調用此函數的腳本中,其後可帶NUM,用於$?的判斷。在return下面的命令不予執行。
}
func2 () {
echo func2
}

diaoyonn.sh
#!/bin/bash
source functions
name=wang
echo diaoyong.sh $name
func1
echo diaoyong.sh $name

/etc/init.d/functions內部有很多函數,用的時候需要重新source該文件,其中有個action函數,是啓動或關閉服務右邊的[ ok ]顯示。

信號捕捉trap



進程收到系統發出的指定信號後,將執行自定義指令,而不會執行原操作

trap '觸發指令' 信號

忽略信號的操作

trap '' 信號

恢復原信號的操作

trap '-' 信號

列出自定義信號操作

trap -p

當腳本退出時,執行finish函數

trap finish EXIT

示例:捕捉kill裏的信號 int=ctrl+c

#!/bin/bash
trap 'echo “signal:SIGINT"' int
trap -p
for((i=0;i<=10;i++))
do
sleep 1
echo $i
done
trap '' int
trap -p
for((i=11;i<=20;i++))
do
sleep 1
echo $i
done
trap '-' int
trap -p
for((i=21;i<=30;i++))
do
sleep 1
echo $i
done

數組



數組:存儲多個元素的連續的內存空間,相當於多個變量的集合
數組名和索引
索引:編號從0開始,屬於數值索引
注意:索引可支持使用自定義的格式,而不僅是數值格式,即爲關聯索引,bash4.0版本之後開始支持
bash的數組支持稀疏格式索引不連續
聲明數組:

declare -a ARRAY_NAME 定義數組爲數字標識從0開始,支持跳躍 默認不定義爲數字標識
declare -A ARRAY_NAME 關聯數組 定義數組爲關聯數組 自定義標識
注意:兩者不可相互轉換

數組賦值
數組元素的賦值(數組支持{}展開,如name=({1..10})引用時可以echo ${name=[0]},打印數組的第一個變量值
(1) 一次只賦值一個元素

ARRAY_NAME[INDEX]=VALUE
weekdays[0]="Sunday"
weekdays[4]="Thursday"

(2) 一次賦值全部元素

ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
name=("zhangsna" "lisi" "wangwu")

(3) 只賦值特定元素

ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
name=([0]="zhangsna" [2]="lisi" [4]="wangwu")

(4) 交互式數組值對賦值(如不定義此項,則表示用數字標識爲角標,否則使用abc)

read -a ARRAY
declare -A name
name=([a]="zhangsna" [c]="lisi" [d]="wangwu")

顯示所有數組:

declare -a

引用數組
引用數組元素

${ARRAY_NAME[INDEX]}
注意:省略[INDEX]表示引用下標爲0的元素

引用數組所有元素

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

數組的長度(數組中元素的個數)

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

刪除數組中的某元素:導致稀疏格式

unset ARRAY[INDEX]

刪除整個數組

unset ARRAY

數組數據處理
引用數組中的元素:
數組切片:

${ARRAY[@]:offset:number}
Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)
offset 要跳過的元素個數
number 要取出的元素個數

取偏移量之後的所有元素

${ARRAY[@]:offset}

向數組中追加元素:

ARRAY[${#ARRAY[*]}]=value
name[${#name[@]}]=7

關聯數組:

declare -A ARRAY_NAME
ARRAY_NAME=([idx_name1]='val1' [idx_name2]='val2‘...)
注意:關聯數組必須先聲明再調用

字符串切片
Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)
${#var}:返回字符串變量var的長度

Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)

${var:offset}:返回字符串變量var中從第offset個字符後(不包括第offset個字符)的字符開始,到最後的部分,offset的取值在0 到 ${#var}-1 之間(bash4.2後,允許爲負值)

Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)

${var:offset:number}:返回字符串變量var中從第offset個字符後(不包括第offset個字符)的字符開始,長度爲number的部分

Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)

${var: -length}:取字符串的最右側幾個字符
注意:冒號後必須有一空白字符

Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)

${var:offset:-length}:從最左側跳過offset字符,一直向右取到距離最右側lengh個字符之前的內容

Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)

${var: -length:-offset}:先從最右側向左取到length個字符開始,再向右取到距離最右側offset個字符之間的內容
注意:-length前空格

Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)

字符串處理

基於模式取子串
${var#*word}:其中word可以是指定的任意字符
功能:自左而右查找var變量存儲的字符串中,第一次出現的word, 刪除字符開頭至第一次出現word字符串(含)之間所有字符

Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)

${var##*word}:同上,貪婪模式,不同的是,刪除的是字符串開頭至最後一次由word指定的字符之間的所有內容

Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)

示例:

file=“var/log/messages”
${file#*/}: log/messages
${file##*/}: messages

${var%word*}:其中word可以是指定的任意字符
功能:自右而左,查找var變量所存儲的字符串中,第一次出現的word, 刪除字符串最後一個字符向左至第一次出現word字符串(含)之間的所有字符

Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)
file="/var/log/messages"
${file%/*}: /var/log

${var%%word*}:同上,只不過刪除字符串最右側的字符向左至最後一次出現word字符之間的所有字符

Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)

示例:

url=http://www.magedu.com:80
${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中的所有大寫字母轉換爲小寫

變量賦值
Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)

高級變量用法-有類型變量
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@server ~]# CMD=whoami
[root@server ~]# echo $CMD
whoami
[root@server ~]# eval $CMD
root
[root@server ~]# n=10
[root@server ~]# echo {0..$n}
{0..10}
[root@server ~]# eval echo {0..$n}
0 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@server ~]# N=NAME
[root@server ~]# NAME=wangxiaochun
[root@server ~]# N1=${!N}
[root@server ~]# echo $N1
wangxiaochun
[root@server ~]# eval N2=\$$N
[root@server ~]# echo $N2
wangxiaochun

創建臨時文件
mktemp命令:創建並顯示臨時文件,可避免衝突

mktemp [OPTION]... [TEMPLATE]
TEMPLATE: filenameXXX
X至少要出現三個

OPTION:

-d: 創建臨時目錄
-p DIR或--tmpdir=DIR:指明臨時文件所存放目錄位置

示例:

mktemp /tmp/testXXX
tmpdir=`mktemp –d /tmp/testdirXXX`
mktemp --tmpdir=/testdir testXXXXXX

安裝複製文件
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
Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)
install –m 770 –d /testdir/installdir
Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)
Linux之編程進階(函數、trap信號捕捉、數組、字符串處理...)

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
expect最常用的語法(tcl語言:模式-動作)

單一分支模式語法:

expect “hi” {send “You said hi\n"}
匹配到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
spawn scp /etc/fstab 192.168.8.100:/app
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "magedu\n" }
}
expect eof
#!/usr/bin/expect
spawn ssh 192.168.8.100
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "magedu\n" }
}
interact
#expect eof

示例:變量

#!/usr/bin/expect
set ip 192.168.8.100
set user root
set password magedu
set timeout 10
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
interact
#./ssh3.exp 192.168.8.100 root magedu

示例:執行多個命令

#!/usr/bin/expect
set ip [lindex $argv 0]
set user [lindex $argv 1]
set password [lindex $argv 2]
set timeout 10
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd haha\n" }
expect "]#" { send "echo magedu |passwd --stdin haha\n" }
send "exit\n"
expect eof
#./ssh4.exp 192.168.8.100 root magedu

示例:shell腳本調用expect

#!/bin/bash
ip=$1
user=$2
password=$3
expect <<EOF
set timeout 20
spawn ssh $user@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect "]#" { send "useradd hehe\n" }
expect "]#" { send "echo magedu |passwd --stdin hehe\n" }
expect "]#" { send "exit\n" }
expect eof
EOF
#./ssh5.sh 192.168.8.100 root magedu
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章