for 循環
for 變量名 in 列表;do
循環體
done
執行機制: 依次將列表中的元素賦值給“變量名”; 每次賦值后即執行一次循環體; 直到列表中
的元素耗盡,循環結束
列表生成方式:
(1)直接給出列表
(2)整數列表:
(a) {start..end}
(b) $(seq [start [step]] end) 例: `seq 1 2 100`
(3)返回列表的命令 $(COMMAND)
(4)使用glob,如:*.sh
(5)變量引用;$@, $*
while 循環
while CONDITION;do
循環體
done
CONDITION :循環控制條件;進入循環之前,先做一次判斷;每一次循環之后會再次做判 斷;條件為“true”則執行一次循環;直到條件測試狀態為“false”終止循環
因此:CONDTION 一般應該有循環控制變量;而此變量的值會在循環體不斷地被修正
進入條件:CONDITION 為true; 退出條件:CONDITION 為false
until 循環
until CONDITION;do
循環體
done
進入條件:CONDITION 為true; 退出條件:CONDITION 為false
循環控制語句continue
用于循環體中
continue [N] :提前結束第N 層的本輪循環,而直接進入下一輪判斷;最內層為第1層
while CONDTIITON1; do
CMD1
…
if CONDITION2; then
continue
fi
CMDn
…
done
循環控制語句break
用于循環體中
break [N] :提前結束第N 層循環,最內層為第1層
while CONDTIITON1; do
CMD1
…
if CONDITION2; then
break
fi
CMDn
…
done
創建無線循環
while true;do
循環體
done
until false;do
循環體
done
while 循環的特殊用法(遍歷文件的每一行)
while read line; do
循環體
done < /PATH/FROM/SOMEFILE
依次讀取/PATH/FROM/SOMEFILE 文件中的每一行,且將行賦值給變量line
for 循環的特殊格式:
for (( 控制變量初始化; 條件判斷表達式; 控制變量的修正表達式))
do
循環體
done
控制變量初始化:僅在運行到循環代碼段時執行一次
控制變量的修正表達式: 每輪循環結束會先進行控制變量修正運算,而后再做條件判斷
雙小括號方法,即((…)) 格式,如((i=1,i++,i<=10))
例:
打印3次10~20(排除15)
continue改為continue 2 或break 跳出里面的for循環,則打印3次10~14
若改為break 2,則跳出整個循環,只打印10~14
select循環與菜單
select variable in list
do
循環體命令
done
select 循環主要用于創建菜單,按數字順序排列的菜單項將顯示在標準錯誤上,并顯示PS3提示
示符,等待用戶輸入
用戶輸入菜單列表中的某個數字,執行相應的命令
用戶輸入被保存在內置變量 REPLY中
select是個無限循環,因此要記住用break命令退出循環,或用 exit命令終止腳本,
也可以按 ctrl+c退出循環。select 經常和case聯合使用
例1: select cmd in ls pwd hostname exit;do $cmd;done
注意:輸入4,執行exit就登出shell了
例2
函數
function f_name {
函數體
}
或
f_name() {
函數體
}
函數的定義和使用:
可在交互式環境下定義函數
可將函數放在腳本文件中作為它的一部分
可放在只包含函數的單獨文件中
調用:函數只有被調用才會執行;
調用:給定函數名
函數名出現的地方,會被自動替換為函數代碼
函數的生命周期:被調用時創建,返回時終止
函數的執行結果返回值:
(1) 使用echo 或printf 命令進行輸出
(2) 函數體中調用命令的輸出結果
函數的退出狀態碼:
(1) 默認取決于函數中執行的最后一條命令的退出狀態碼
(2) 自定義退出狀態碼,其格式為:
return 從函數中返回,用最后狀態命令決定返回值
return 0 無錯誤返回
return 1-255 有錯誤返回
使用函數文件
可以將經常使用的函數存入函數文件,然后將函數文件載入shell
一旦函數文件載入shell,就可以在命令行或腳本中調用函數??梢允褂?/span>set命令查看所有定義的函數,其輸出列表包括已經載入shell 的所有函數;若要改動函數,首先用unset命令從shell中刪除函數,改動完畢后,再重新載入此文件
function fun1 (){ echo "this is a fun1";}
# fun1 輸出this is a fun1
set命令看到存在內存中的變量fun1
unset fun1 再set查看就沒有這個變量了,# fun1 輸出command not found
function fun3 () { echo "this is a func3";return;echo "xxxx"; }
#fun3 只輸出this is a func3 return后面的不執行
echo $? 返回0
return后面自定義級別,如return 100
執行fun3 再echo $? 返回100
載入函數
. filename 或 source filename
函數變量
變量作用域:
環境變量:當前shell和子shell有效
本地變量:只在當前shell進程有效,為執行腳本會啟動專用子shell進程;因此本地變量的作用范圍是當前shell 腳本程序文件,包括腳本中的函數。
局部變量:函數的生命周期;函數結束時變量被自動銷毀
注意:如果函數中有局部變量,如果其名稱同本地變量,使用局部變量
在函數中定義局部變量的方法 local NAME=VALUE
1.判斷/var/ 目錄下所有文件的類型
for i in /var/*;do echo $i|filetype.sh;done |sed -n '2~2p' (用到函數調用)
2.添加10個用戶user1-user10,密碼同用戶名
#!/bin/bash
for i in {1..10}
do
useradd user$i
echo "user$i"|passwd –stdin user$i
done
3./etc/rc.d/rc3.d 目錄下分別有多個以K開頭和以S開頭的文件;分別讀取每個文件,以K 開頭的文件輸出為文件加stop,以S開頭的文件輸出為文件名加start;
“K34filename stop” “S66filename start”
#!/bin/bash
cd /etc/rc.d/rc3.d
for i in /etc/rc.d/rc3.d/*;do
b=`basename /etc/rc.d/rc3.d/$i`
j=`echo $b|cut -c1`
if [ $j == 'K' ];then
cp $b "$b"_stop
elif [ $j == 'S' ];then
cp $b "$b"_start
fi
done
4.寫一個腳本,提示輸入正整數n 的值,計算1+2+3+…n的總和
#!/bin/bash
read -p "Input a positive number: " n
if [ $[$n/1] -gt 0 ];then
echo sum=`seq -s+ 1 $n|bc`
elif [ $[$n/1] -lt 0 ];then
echo negative number is not allowed
elif [ $n == 0 ];then
echo Zero!
else
echo other input is illegal
fi
5.寫一個腳本,提示請輸入網絡地址,如172.18.18.0 ,判斷輸入的網段中主機在線狀態
#!/bin/bash
for ip in `seq 1 255`
do
{
ping -c 1 172.18.18.$ip > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo 172.18.18.$ip UP
else
echo 172.18.18.$ip DOWN
fi
}&
done
6.打印乘法表(if / while)
#!/bin/sh
for i in {1..9};do
for ((j=1;j<=9;j++));do
echo -n "$j*$i=$(($j*$i)) "
if [ $j -ge $i ];then
echo
break
fi
done
done
或
#!/bin/sh
i=1
j=1
while [ "$i" -ne 10 ];do
while [ "$j" -le $i ];do
echo -ne "$i*$j=$(($i*$i)) \t"
let j++
done
j=1
let i++
echo
done
7.求100以內所有正整數之和(while)
#!/bin/bash
read -p "Input a positive number: " n
a=0
while [ $a -le $n ];do
sum=`seq -s+ 1 $a`
let a++
done
echo $sum|bc
8.通過ping 命令探測192.168.1.1-254范圍內的所有主機的在線狀態,統計在線主機和離線主機各多少
#!/bin/bash
read -p "Input the ip: " ip
i=`echo $ip | cut -d. -f1-3`.
j=0
if echo $ip | egrep "^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]).(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]).){2}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$" ;then
while [ $j -le 255 ] ;do
ping -c1 -W1 $i$j &> /dev/null && echo "$i$j is online" ||echo "$i$j is offline"
let j++
done
else
echo "Illegal input"
fi
9.利用變量RANDOM生成10個隨機數字,輸出這個10數字,并顯示其中的最大者和最小者(while)
#!/bin/bash
echo > rnu
frequency=1
while [ $frequency -le 10 ];do
echo $[$RANDOM] >> rnu
let frequency++
done
ten_random=`cat rnu|sed -e 1d`
echo "Ten random number are"
echo $ten_random
echo -e "\033[31mmax=`cat rnu|tr " " "\n"|sort -n|tail -1`\033[0m"
echo -e "\033[32mmin=`cat rnu|tr " " "\n"|sort -n|sed -n 2p`\033[0m"
10.打印國際象棋棋盤
#!/bin/bash
for i in {1..8}; do
for ((j=1;j<=8;j++)); do
if [ $[($i+$j)%2] -eq 0 ]; then
echo -ne "\033[47m \033[0m"
else
echo -ne "\033[40m \033[0m"
fi
if [ $j -eq 8 ]; then
echo -ne "\n"
fi
done
done
11.每隔3秒鐘到系統上獲取已經登錄的用戶的信息;如果發現用戶hacker 登錄,則將登錄時 間和主機記錄于日志/var/log/login.log 中, 并提示該用戶退出系統
#!/bin/bash
until who |grep -q "^hacker\b" ;do
sleep 3
done
who | grep "^hacker"|tr -s ' '|cut -d' ' -f3,5 >> /var/log/login.log
echo "you should logout system" | mail hacker
echo "reminded and login record in /var/log/login.log"
12. 隨機生成10以內的數字,實現猜字游戲,提示比較大或小,相等則退出。
#!/bin/bash
read -p "Input a number: " m
n=$[$RANDOM%10+1]
until [[ $m -eq $n ]];do
[ $m -lt $n ] && echo "It's small,guess bigger"
[ $m -gt $n ] && echo "It's big,guess smaller"
read -p "Input a number: " m
done
echo Right!
13.打印松塔
#!/bin/bash
#i是當前行數,j是空格數量,h是星號數量
read -p "Please Enter a number:" Row
for ((i=1; i<=Row; i++))
do
for ((j=$Row-$i; j>0; j–));
do
echo -n ' '
done
for ((h=1; h<=$((2*$i-1)); h++))
do
echo -ne '\033[32m*\033[0m'
done
echo
done
14.用until循環實現國際象棋棋盤
#!/bin/bash
i=1
j=1
until [ $i -gt 8 ]
do
until [ $j -gt 8 ]
do
if [ $[(($i+$j))%2] -eq 1 ];then
echo -ne "\033[47m \033[0m"
else
echo -ne "\033[40m \033[0m"
fi
let j++
done
echo
let i++
j=1
done
15.編寫服務腳本/root/bin/testsrv.sh,完成如下要求
(1) 腳本可接受參數:start, stop, restart, status
(2) 如果參數非此四者之一,提示使用格式后報錯退出
(3) 如是start:則創建/var/lock/subsys/SCRIPT_NAME, 并顯示“啟動成功”
考慮:如果事先已經啟動過一次,該如何處理?
(4) 如是stop:則刪除/var/lock/subsys/SCRIPT_NAME, 并顯示“停止完成”
考慮:如果事先已然停止過了,該如何處理?
(5) 如是restart,則先stop, 再start
考慮:如果本來沒有start,如何處理?
(6) 如是status, 則如果/var/lock/subsys/SCRIPT_NAME文件存在,則顯示“SCRIPT_NAME is running…”
如果/var/lock/subsys/SCRIPT_NAME文件不存在,則顯示“SCRIPT_NAME is stopped…”
其中:SCRIPT_NAME為當前腳本名
#!/bin/bash
fstart () {
if [ -e "$1" ]; then
echo "Already start"
else
touch $ff
echo "Start Successfully!"
fi
}
fstop () {
if [ -e "$1" ] ; then
rm -f $1
echo "Stop Successfully!"
else
echo "Already stop"
fi
}
frestart() {
if [ -e "$1" ] ; then
fstop &> /dev/null
fstart &> /dev/null
echo "Restart successful"
else
fstart &> /dev/null
echo "start successful "
fi
}
fstatus () {
if [ -e "$1" ] ;then
echo "testsrv is runing…"
else
echo "testsrv is stopped…"
fi
}
select choice in start stop restart status quit
do
ff=/var/lock/subsys/testsrv.sh
case $choice in
start)
fstart $ff
;;
stop)
fstop $ff
;;
restart)
frestart $ff
;;
status)
fstatus $ff
;;
quit)
break
;;
*)
echo "error!"
exit 2
esac
done
16. 編寫腳本/root/bin/copycmd.sh
(1)提示用戶輸入一個可執行命令名稱;
(2)獲取此命令所依賴到的所有庫文件列表
(3)復制命令至某目標目錄(例如/mnt/sysroot)下的對應路徑下;
如:/bin/bash ==> /mnt/sysroot/bin/bash
/usr/bin/passwd==> /mnt/sysroot/usr/bin/passwd
(4)復制此命令依賴到的所有庫文件至目標目錄下的對應路徑下:
如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2
(5)每次復制完成一個命令后,不要退出,而是提示用戶鍵入新的要復制的命令,并重復完成上 述功能;直到用戶輸入quit退出
#!/bin/bash
copycmd(){
for eachline in `ldd $fullname | sed -r -n 's@.*> (/.*) \(.*$@\1@p'`
do
local path=`dirname $eachline`
mkdir -p /mnt/sysroot/$path &>/dev/null
cp -p $eachline /mnt/sysroot/$path &>/dev/null
done
}
while true
do
read -p "請輸入一個可執行的命令名稱 " cmds
which $cmds
if [ $? -eq 0 ]
then
fullname=`\which $cmds`
path=`dirname $fullname`
mkdir -p /mnt/sysroot/$path &>/dev/null
cp -p $fullname /mnt/sysroot/$path &>/dev/null
copycmd
elif [[ $cmds == "quit" ]]
then
break
else
echo "輸入的命令不對"
fi
done
17.寫一個函數實現數字的加減乘除運算,例如輸入1+2 ,將得出正確結果
vim mathfun
#!/bin/bash
function multiplications () {
let multiplication=$1\*$2
echo "積為:$multiplication"
}
function divisions () {
let division=$1/$2
echo "商為:$division"
}
function pluss () {
let plus=$1+$2
echo "和為:$plus"
}
function subtractions {
let subtraction=$1-$2
echo "差為:$subtraction"
}
vim funset
#!/bin/bash
source mathfun
echo "1st arg is $1"
echo "2st arg is $2"
pluss $1 $2
divisions $1 $2
multiplications $1 $2
subtractions $1 $2
18. 0,1,2,3,5,8,13,21,34…… ,斐波納契數列以如下被以遞歸的方法定義:
F(0)=0 ,F(1)=1 ,F(0)=F(n-1)+F(n-2) (n≥2)
寫一個函數,求n階斐波那契數列
#!/bin/bash
rabbit() {
if [ $1 -eq 0 ];then
echo 0
elif [ $1 -eq 1 ];then
echo 1
else
echo "$[$(rabbit $[$1-1])+$(rabbit $[$1-2])]"
fi
}
rabbit $1
19.利用函數,實現N片盤的漢諾塔的移動步驟
#!/bin/bash
hannuo() {
if [ $1 -eq 1 ];then
echo "from $2 to $4"
else
hannuo `expr $1 – 1` $2 $4 $3
echo "from $2 to $4"
hannuo `expr $1 – 1` $3 $2 $4
fi
}
read -p "Input the number: " n
hannuo $n 'A' 'B' 'C'
20.掃描/etc/passwd 文件每一行,如發現GECOS 字段為空,則填充用戶名和單位電話為62985 6,并提示該用戶的GECOS信息修改成功
#!/bin/bash
while read line ; do
var=`echo $line | cut -d ":" -f 5`
user=`echo $line | cut -d ":" -f 1`
[[ -z "${var}" ]] && chfn -f ${user} -p 629856 ${user};echo "${user}'s information
change successful"
done < /etc/passwd
原創文章,作者:victorycommander,如若轉載,請注明出處:http://www.www58058.com/39013