linux shell 高级编程,shell高级编程
條件選擇if語句
選擇執(zhí)行: 注意:if語句可嵌套
單分支
if 判斷條件;then
條件為真的分支代碼
fi
雙分支
if 判斷條件; then
條件為真的分支代碼
else條件為假的分支代碼
fi
多分支
if 判斷條件1; then
條件為真的分支代碼
elif 判斷條件2; then
條件為真的分支代碼
elif 判斷條件3; then
條件為真的分支代碼
else以上條件都為假的分支代碼
fi
逐個條件進(jìn)行判斷,第一次遇為“真”條件時,執(zhí)行其分支,而后結(jié)束整個if語
句
If示例
根據(jù)命令的退出狀態(tài)來執(zhí)行命令
if ping -c1 -W2 station1 &> /dev/null; then
echo 'Station1 is UP'
elif grep "station1" ~/maintenance.txt &> /dev/null
then
echo 'Station1 is undergoing maintenance‘
else echo 'Station1 is unexpectedly DOWN!' exit 1
fi
條件判斷:case語句
case 變量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...*)
默認(rèn)分支
;;
esac
case支持glob風(fēng)格的通配符:
*: 任意長度任意字符
?: 任意單個字符
[]:指定范圍內(nèi)的任意單個字符
a|b: a或b
for循環(huán)
for 變量名 in 列表;do
循環(huán)體
done
執(zhí)行機(jī)制:
依次將列表中的元素賦值給“變量名”; 每次賦值后即執(zhí)行一次循環(huán)體; 直到列表中的元素
耗盡,循環(huán)結(jié)束
列表生成方式:
(1) 直接給出列表
(2) 整數(shù)列表:
(a) {start..end}
(b) $(seq [start [step]] end)
(3) 返回列表的命令$(COMMAND)
(4) 使用glob,如:.sh
(5) 變量引用;$@, $
while循環(huán)
while CONDITION; do
循環(huán)體
done
CONDITION:循環(huán)控制條件;進(jìn)入循環(huán)之前,先做一次判斷;每一次循環(huán)之后會再次判斷;條件
為“true”,則執(zhí)行一次循環(huán);直到條件測試狀態(tài)為“false”終止循環(huán)
因此:CONDTION一般應(yīng)該有循環(huán)控制變量;而此變量的值會在循環(huán)體不斷地被修正
進(jìn)入條件:CONDITION為true
退出條件:CONDITION為false
until循環(huán)
until CONDITION; do
循環(huán)體
done
進(jìn)入條件: CONDITION 為false
退出條件: CONDITION 為true
循環(huán)控制語句continue
用于循環(huán)體中
continue [N]:提前結(jié)束第N層的本輪循環(huán),而直接進(jìn)入下一輪判斷;最內(nèi)層為第1層
while CONDTIITON1; do
CMD1
...
if CONDITION2; then
continue
fi
CMDn
...
done
循環(huán)控制語句break
用于循環(huán)體中
break [N]:提前結(jié)束第N層循環(huán),最內(nèi)層為第1層
while CONDTIITON1; do
CMD1...if CONDITION2; then
breakfiCMDn...done
示例:doit.sh
#!/bin/bash
Name: doit.sh
Purpose: shift through command line arguments
Usage: doit.sh [args]
while [ $# -gt 0 ] # or (( $# > 0 ))
doecho $*
shiftdone
示例:shift.sh
#!/bin/bash
#step through all the positional parameters
until [ -z "$1" ]
doecho "$1"
shiftdoneecho
創(chuàng)建無限循環(huán)
while true; do
循環(huán)體
done
until false; do
循環(huán)體
Done
特殊用法
while循環(huán)的特殊用法(遍歷文件的每一行):
while read line; do
循環(huán)體
done < /PATH/FROM/SOMEFILE
依次讀取/PATH/FROM/SOMEFILE文件中的每一行,且將行賦值給變量line
練習(xí)
掃描/etc/passwd文件每一行,如發(fā)現(xiàn)GECOS字段為空,則填充用戶名和單位電話為62985600,并提示該
用戶的GECOS信息修改成功。
#!/bin/bash
while read line ;do
gecos=$(echo $line |cut -d: -f5)
if [ -z "$gecos" ];then
UserName=$(echo $line |cut -d: -f1)
usermod -c "$UserName 62985600" $UserName
echo "$UserName's gecos changed"
fi
done < /etc/passwd
編寫個腳本,會對系統(tǒng)中已存在的用戶進(jìn)行身份判斷,若為centos7,則uid大于1000的用戶將判斷為comm user,反之判定為sys user, 若為centos6,則uid大于500的用戶判斷為comm user,反之sys user.輸出格式如下
root: sys user
……
liubei: comm user
#!/bin/bash
release=$(cat /etc/centos-release| sed -r 's/.* ([0-9]+)..*/\1/')
while read line; do
uid=$(echo $line | cut -d: -f3)
name=$(echo $line | cut -d: -f1)
if [ $release = 6 -a $uid -lt 500 ] || [ $release = 7 -a $uid -lt 1000 ]; then
echo "$name: sys user"
else
echo "$name: comm user"
fi
done < /etc/passwd
找出分區(qū)利用率大于10%的分區(qū),顯示結(jié)果如下:
/dev/sda1 will be full : 33%
/dev/sda2 will be full : 99%
#!/bin/bash
df |grep /dev/sd |while read line;do
used=$(echo $line |tr -s " " % |cut -d% -f5)
name=$(echo $line |cut -d" " -f1)
if (( $used > 10 ));then
echo "$name will be full:$used%"
fi
done
特殊用法
雙小括號方法,即((…))格式,也可以用于算術(shù)運(yùn)算
雙小括號方法也可以使bash Shell實(shí)現(xiàn)C語言風(fēng)格的變量操作
I=10((I++))
for循環(huán)的特殊格式:
for ((控制變量初始化;條件判斷表達(dá)式;控制變量的修正表達(dá)式))
do循環(huán)體
done控制變量初始化:僅在運(yùn)行到循環(huán)代碼段時執(zhí)行一次
控制變量的修正表達(dá)式:每輪循環(huán)結(jié)束會先進(jìn)行控制變量修正運(yùn)算,而后再做條件判斷
for ((i=1;i<=100;i++));do
let sum+=i
done
echo sum=$sum
select循環(huán)與菜單
select variable in list
do
循環(huán)體命令
done
select 循環(huán)主要用于創(chuàng)建菜單,按數(shù)字順序排列的菜單項(xiàng)將顯示在標(biāo)準(zhǔn)錯誤上,并顯示 PS3 提示符,等待用戶輸入
用戶輸入菜單列表中的某個數(shù)字,執(zhí)行相應(yīng)的命令
用戶輸入被保存在內(nèi)置變量 REPLY 中[][][]
select 是個無限循環(huán),因此要記住用 break 命令退出循環(huán),或用 exit 命令終止腳本。也可以按
ctrl+c 退出循環(huán)
select 經(jīng)常和 case 聯(lián)合使用
與 for 循環(huán)類似,可以省略 in list,此時使用位置參量
練習(xí):為某餐館用Shell制作一個點(diǎn)菜系統(tǒng)。
執(zhí)行腳本,會列出主菜單,如下
請問吃什么?
1) 飯
2) 面
3)餃子
4)不吃
等待用戶選擇
如選擇1,則再問,選擇完后報(bào)價
1) 炒飯
2)蓋飯
3)木桶飯
如選擇2,則再問
1)炒面
2)蓋面
3)拉面
4)拌面
如選擇3,則再問
1)豬肉大蔥
2)素三鮮
3)韭菜雞蛋
每項(xiàng)選擇后,最終會報(bào)價,如
木桶飯: 10元
如選擇4,則退出
#!/bin/bash
PS3="Please choose your food: "
echo "請問吃什么"
caidan() {
select menu in 飯 面 餃子 不吃;do
case $REPLY in
1) select fan in 炒飯 蓋飯 木桶飯 返回;do
case $REPLY in
1) echo "炒飯: 10";break 2;;
2) echo "蓋飯: 12";break 2;;
3) echo "木桶飯:15";break 2;;
4) caidan;;
esac
done
;;
2) select mian in 炒面 蓋面 拉面 拌面 返回;do
case $REPLY in
1) echo "炒面: 10";break 2;;
2) echo "蓋面: 12";break 2;;
3) echo "拉面:15";break 2;;
4) echo "拌面: 18";break 2;;
5) caidan;;
esac
done
;;
3) select jiaozi in 豬肉大蔥 素三鮮 韭菜雞蛋 返回;do
case $REPLY in
1) echo "豬肉大蔥: 10";break 2;;
2) echo "素三鮮: 12";break 2;;
3) echo "韭菜雞蛋:15";break 2;;
4) caidan;;
esac
done
;;
4) exit;;
esac
done
}
caidan
信號捕捉trap
trap '觸發(fā)指令' 信號
自定義進(jìn)程收到系統(tǒng)發(fā)出的指定信號后,將執(zhí)行觸發(fā)指令,而不會執(zhí)行原操作
trap '' 信號
忽略信號的操作
trap '-' 信號
恢復(fù)原信號的操作
trap -p
列出自定義信號操作
trap示例
#!/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
函數(shù)介紹
函數(shù)function是由若干條shell命令組成的語句塊,實(shí)現(xiàn)代碼重用和模塊化編程
它與shell程序形式上是相似的,不同的是它不是一個單獨(dú)的進(jìn)程,不能獨(dú)立運(yùn)行,而是shell程序的一部分
函數(shù)和shell程序比較相似,區(qū)別在于:
1.Shell程序在子Shell中運(yùn)行
2. 而Shell函數(shù)在當(dāng)前Shell中運(yùn)行。因此在當(dāng)前Shell中,函數(shù)可以對shell中變量進(jìn)行修改
定義函數(shù)
? 函數(shù)由兩部分組成:函數(shù)名和函數(shù)體 ? help function
? 語法一:
function f_name
{
...函數(shù)體...
}
? 語法二:
function f_name ()
{
...函數(shù)體...
}
? 語法三:
f_name ()
{
...函數(shù)體...
}
函數(shù)使用
? 函數(shù)的定義和使用: – 可在交互式環(huán)境下定義函數(shù) – 可將函數(shù)放在腳本文件中作為它的一部分 – 可放在只包含函數(shù)的單獨(dú)文件中 ? 調(diào)用:函數(shù)只有被調(diào)用才會執(zhí)行
調(diào)用:給定函數(shù)名
函數(shù)名出現(xiàn)的地方,會被自動替換為函數(shù)代碼
? 函數(shù)的生命周期:被調(diào)用時創(chuàng)建,返回時終止
檢查載入函數(shù)
使用set命令檢查函數(shù)是否已載入。set命令將在shell中顯示所有的載入函
數(shù)
示例:
set
findit=( ){
if [ $# -lt 1 ]; the
echo "usage :findit file";
return 1
fi
find / -name $1 -print
}…
刪除shell函數(shù)
現(xiàn)在對函數(shù)做一些改動后,需要先刪除函數(shù),使其對shell不可用。使用unset命令完成刪除函數(shù)
命令格式為:
unset function_name
示例:
unset findit
再鍵入set命令,函數(shù)將不再顯示
環(huán)境函數(shù)
使子進(jìn)程也可使用
聲明:export –f function_name
查看:export -f 或 declare -xf
函數(shù)可以接受參數(shù):
傳遞參數(shù)給函數(shù):調(diào)用函數(shù)時,在函數(shù)名后面以空白分隔給定參數(shù)列表即可;例如
“testfunc arg1 arg2 ...”
在函數(shù)體中當(dāng)中,可使用$1, $2, ...調(diào)用這些參數(shù);還可以使用$@, $*, $#等特殊變量
馬函數(shù)變量
變量作用域:
環(huán)境變量:當(dāng)前shell和子shell有效
本地變量:只在當(dāng)前shell進(jìn)程有效,為執(zhí)行腳本會啟動專用子shell進(jìn)程;因此,本地變量
的作用范圍是當(dāng)前shell腳本程序文件,包括腳本中的函數(shù)
局部變量:函數(shù)的生命周期;函數(shù)結(jié)束時變量被自動銷毀
注意:如果函數(shù)中有局部變量,如果其名稱同本地變量,使 用局部變量
在函數(shù)中定義局部變量的方法
local NAME=VALUE
函數(shù)遞歸示例
函數(shù)遞歸:
函數(shù)直接或間接調(diào)用自身
注意遞歸層數(shù)
遞歸實(shí)例:
階乘是基斯頓·卡曼于 1808 年發(fā)明的運(yùn)算符號,是數(shù)學(xué)術(shù)語
一個正整數(shù)的階乘(factorial)是所有小于及等于該數(shù)的正整數(shù)的積,并且有0的階乘為1,自然數(shù)n的
階乘寫作n!
n!=1×2×3×...×n階乘亦可以遞歸方式定義:0!=1,n!=(n-1)!×n
n!=n(n-1)(n-2)...1
n(n-1)! = n(n-1)(n-2)!
#!/bin/bash
#fact() {
if [ $1 -eq 0 -o $1 -eq 1 ]; then
echo 1
else
echo $[$1*$(fact $[$1-1])]
fi
}
fact $1
×××
fork×××是一種惡意程序,它的內(nèi)部是一個不斷在fork進(jìn)程的無限循環(huán),實(shí)質(zhì)是一個簡單的遞歸
序。由于程序是遞歸的,如果沒有任何限制,這會導(dǎo)致這個簡單的程序迅速耗盡系統(tǒng)里面的所有資
源
函數(shù)實(shí)現(xiàn)
:(){ :|:& };:
bomb() { bomb | bomb & }; bomb
腳本實(shí)現(xiàn)
cat Bomb.sh
#!/bin/bash
./$0|./$0&
數(shù)組
變量:存儲單個元素的內(nèi)存空間
數(shù)組:存儲多個元素的連續(xù)的內(nèi)存空間,相當(dāng)于多個變量的集合
數(shù)組名和索引
索引:編號從0開始,屬于數(shù)值索引
注意:索引可支持使用自定義的格式,而不僅是數(shù)值格式,即為關(guān)聯(lián)
索引,bash4.0版本之后開始支持
bash的數(shù)組支持稀疏格式(索引不連續(xù))
聲明數(shù)組:
declare -a ARRAY_NAME
declare -A ARRAY_NAME: 關(guān)聯(lián)數(shù)組
注意:兩者不可相互轉(zhuǎn)換
數(shù)組賦值
數(shù)組元素的賦值:
(1) 一次只賦值一個元素;
ARRAY_NAME[INDEX]=VALUE
weekdays[0]="Sunday
weekdays[4]="Thursday
(2) 一次賦值全部元素:
ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
(3) 只賦值特定元素:
ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
(4) 交互式數(shù)組值對賦值
read
-a ARRAY
顯示所有數(shù)組:declare
-a
引用數(shù)組
引用數(shù)組元素:
${ARRAY_NAME[INDEX]}
注意:省略[INDEX]表示引用下標(biāo)為
0的元素
引用數(shù)組所有元素:
${ARRAY_NAME[*]}
${ARRAY_NAME[@]}
數(shù)組的長度
(數(shù)組中元素的個數(shù)
)
:
${#ARRAY_NAME[*]}
${#ARRAY_NAME[@]}
刪除數(shù)組中的某元素:導(dǎo)致稀疏格式
unset ARRAY[INDEX]
刪除整個數(shù)組
unset ARRAY
數(shù)組數(shù)據(jù)處理
引用數(shù)組中的元素:
數(shù)組切片:${ARRAY[@]:offset:number}
offset: 要跳過的元素個數(shù)
number: 要取出的元素個數(shù)
取偏移量之后的所有元素
${ARRAY[@]:offset}
向數(shù)組中追加元素:
ARRAY[${#ARRAY[*]}]=value
關(guān)聯(lián)數(shù)組:
declare -A ARRAY_NAME ARRAY_NAME=([idx_name1]='val1'
[idx_name2]='val2‘...)
注意:關(guān)聯(lián)數(shù)組必須先聲明再調(diào)用
示例
生成10個隨機(jī)數(shù)保存于數(shù)組中,并找出其最大值和最小值
#!/bin/bash
declare -a rand
declare -i max=0
declare –i min=32767
for i in {0..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"
示例
編寫腳本,定義一個數(shù)組,數(shù)組中的元素是/var/log目錄下所有以.log結(jié)尾的
文件;要統(tǒng)計(jì)其下標(biāo)為偶數(shù)的文件中的行數(shù)之和
#!/bin/bash
#declare -a files
files=(/var/log/*.log)
declare -i lines=0
for i in $(seq 0 $[${#files[*]}-1]); do
if [ $[$i%2] -eq 0 ];then
let lines+=$(wc -l ${files[$i]} | cut -d' ' -f1)
fi
done
echo "Lines: $lines."
總結(jié)
以上是生活随笔為你收集整理的linux shell 高级编程,shell高级编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: An Energy-Efficient
- 下一篇: android打开4g开关,【VoLTE