shell腳本編程進階

shell腳本編程進階

循環

編程中的邏輯處理:
順序執行
選擇執行
循環執行
php

循環執行
將某代碼段重複運行屢次
重複運行多少次
循環次數事先已知
循環次數事先未知
有進入條件和退出條件html

for, while, untilgit

for, while, until 這些都是關鍵字 算法

for 循環

help for  查看幫助信息shell

for: for NAME [in WORDS ... ] ; do COMMANDS; doneapache

for 變量名 in 列表;do
循環體
done
執行機制:
依次將列表中的元素賦值給「變量名」; 每次賦值後即執行一次循環體; 直
到列表中的元素耗盡,循環結束編程

列表生成方式:
(1) 直接給出列表
(2) 整數列表:
(a) {start..end}
(b) $(seq [start [step]] end)
(3) 返回列表的命令
$(COMMAND)
(4) 使用glob,如:*.sh
(5) 變量引用
$@, $*vim

舉例:數組

//打印
[root@CentOS7 scripts]# for i in 1 a Z;do echo abc;done
[root@CentOS7 scripts]# for i in 1 2 333;do echo $i;done
[root@CentOS7 scripts]# for i in {1..10};do echo $i;done
[root@CentOS7 scripts]# for i in {10..5};do echo $i;done
[root@CentOS7 scripts]# for i in {10..5..2};do echo $i;done
[root@CentOS7 scripts]# for i in `seq 10 -3 1`;do echo $i;done

// "*.txt" 與 *.txt
[root@CentOS7 data]# for file in "*.txt";do echo filename is $file;done
filename is f10.txt f1.txt f2.txt f3.txt f4.txt f5.txt f6.txt f7.txt f8.txt f9.txt
[root@CentOS7 data]# for file in *.txt;do echo filename is $file;done
filename is f10.txt
filename is f1.txt
filename is f2.txt
filename is f3.txt
filename is f4.txt
filename is f5.txt
filename is f6.txt
filename is f7.txt
filename is f8.txt
filename is f9.txt

// "$*" 與 "$@" 
[root@CentOS7 scripts43]# cat for_test.sh 
#!/bin/bash
#
for i in "$*";do
	echo arg is $i
done
[root@CentOS7 scripts43]# sh for_test.sh a b c
arg is a b c


[root@CentOS7 scripts43]# cat for_test1.sh 
#!/bin/bash
#
for i in "$@";do
	echo arg is $i
done
[root@CentOS7 scripts43]# sh for_test1.sh a b c
arg is a
arg is b
arg is c

//從1加到100的和
[root@CentOS7 scripts43]# cat 1-100.sh
#!/bin/bash
#
sum=0
for i in {1..100};do
	let sum+=$i	
done
ADD=`echo -n {1..100}|tr -s ' ' '+'`
echo "$ADD=$sum"

//100之內奇數的和
[root@CentOS7 scripts43]# cat even1.sh
#!/bin/bash
#
declare -i sum=0
for i in {1..100};do
	if [ $[i%2] -eq 1 ];then
		let sum+=i
	fi
done
echo sum=$sum

//建立用戶user1-user10,密碼隨機,第一次用戶登錄時必須改密碼
[root@CentOS7 scripts43]# cat adduser1-10.sh 
#!/bin/bash
#
for i in {1..10};do  // `cat userlist`,一個變量(一行一個用戶)
	user=`echo user$i`
	password=`tr -dc '[:alnum:]' < /dev/urandom|head -c12`
	useradd $user
	echo $user:$password |tee -a user.list|chpasswd
	passwd -e $user
	echo "User:$user is create"
done

//刪除新建的用戶
for user in `sed -nr '/^alice/,$s/^([^:]+).*/\1/p' /etc/passwd`;do userdel -r $user;done

//將文件名後綴改成 hml
[root@CentOS7 test]# ls
1.txt  2.log  3.html
[root@CentOS7 test]# for i in `ls -1`;do mv $i `echo $i|sed -r 's@\..*$@@'`.hml;done


//查看在線主機
[root@CentOS7 scripts]# cat ping.sh
#!/bin/bash
#
NETID=192.168.1
for HOSTID in {1..254};do
	{
	if ping -c1 -W1 $NETID.$HOSTID >/dev/null;then
		echo "$NETID.$HOSTID is up"|tee -a iplist.txt
	fi
	} &
done
wait

//打印閃爍的**矩形(每一個*的顏色隨機)

[root@CentOS7 scrips43]# 
[root@CentOS7 scrips43]# cat for_test.sh 
#!/bin/bash
#
read -p "please input row: " ROW
read -p "please input column: " COLUMN
COLOR="\033["
for i in `seq $ROW`;do
	for j in `seq $COLUMN`;do
		echo -e "${COLOR}$[$RANDOM%7+31];1;5m*\033[0m\c"
	done
	echo
done

// 九九乘法表(第一個數爲列的編號,第二個數爲行的編號,行號與列的最大值相等)
[root@CentOS7 scrips43]# cat for_9x9.sh 
#!/bin/bash
#
for i in {1..9};do
	for j in `seq $i`;do
		echo -e "$j*$i=$[j*i]\t\c"
	done
	echo
done

// tac 九九乘法表
[root@CentOS7 scrips43]# cat for_tac_9x9.sh
#!/bin/bash
#
for i in {9..1};do
	for j in `seq $i`;do
		echo -e "$j*$i=$[j*i]\t\c"
	done
	echo
done

c風格的 for 循環bash

 

//c風格for循環,打印1到100的和
[root@CentOS7 scrips43]# cat c_for_1-100.sh
#!/bin/bash
#
declare -i sum=0
for((i=1;i<=100;i++));do   // 100 能夠用變量來代替
	let sum+=i
done
echo sum=$sum

[root@CentOS7 scrips43]# cat c_for_1-100.sh
#!/bin/bash
#
for((sum=0,i=1;i<=100;i++));do
	let sum+=i
done
echo sum=$sum

//c風格for循環,九九乘法表

[root@CentOS7 scrips43]# cat c_9x9.sh 
#!/bin/bash
#
for((i=1;i<=9;i++));do
	for((j=1;j<=i;j++));do
		echo -e "$j*$i=$[j*i]\t\c"
	done
	echo
done

打印一個等腰三角形

 

 

[root@CentOS7 scrips43]# cat triangle.sh 
#!/bin/bash
#
read -p "please input row: " ROW
for((i=1;i<=ROW;i++));do
	for((j=1;j<=ROW-i;j++));do
		echo -e " \c"
	done
	for((x=1;x<=i*2-1;x++));do
		echo -e "*\c"
	done
	echo
done

 

 while 循環

while CONDITION; do 循環體;done

CONDITION: 循環控制條件;進入循環以前,先作一次判斷;每一次循環以後會再次作判斷;條件爲 true,則執行一次循環;直到條件測試狀態爲 false 終止循環。

所以:CONDITION 通常應該有循環控制變量;而此變量的值會在循環體不斷地被修正

進入條件:CONDITION爲 true

退出條件:CONDITION 爲 false

//隨機生成10個數字,打印最大值和最小值
[root@CentOS7 scrips43]# cat while_max_min.sh 
#!/bin/bash
#
MAX=$RANDOM
MIN=$MAX
i=1
while [ $i -lt 10 ];do
	N=$RANDOM
	echo $N
	if [ $N -gt $MAX ];then
		MAX=$N
	elif [ $N -lt $MIN ];then
		MIN=$N
	fi
	let i++
done
echo max=$MAX,min=$MIN

可以判斷某個服務是正常工做的,若是這個服務出現異常,咱們但願把對應的服務啓動起來

  1. yum install php-fpm -y
  2. service php-fpm start
  3. vim /data/scripts/monitor_php-fpm.sh
  4. killall php-fpm
  5.  bash while_monitor_php-fpm.sh
  6. 應該放在一個 screen中在後臺運行 這個腳本
  7. 查看日誌

until 循環

until CONDITION;do  (與條件相反時才執行)

    循環體

done

continue ; break ; exit  ;  continue 2 ;break 2;

  1. continue,break 均可用在循環中
  2. continue表示結束這次循環,繼續下一次循環
  3. break表示結束一輪循環,退出當前循環
  4. exit表示退出程序
  5. continue 2 表示結束當前循環的外層循環
  6. break 2 表示退出當前循環的外層循環

循環控制 shift 命令

  1. shift [n]
  2. 用於將參量列表左移指定次數,缺省爲左移一次
  3. 參量列表一旦被移動,最左端的那個參數就從列表中刪除。while循環遍歷位置參量列表時,經常使用到 shift

建立無限循環

  1. while:;do 循環體;done
  2. until false;do 循環體;done

信號捕捉 trap

  1. trap 'cmd' signal_spec ...             // 進程收到系統發出的指定信號後,將執行自定義指令,而不會執行原操做
  2. trap '' signal_spec ...                  // 忽略信號的操做
  3. trap '-' signal_spec ...               // 恢復信號的操做
  4. trap -p                                    // 列出自定義信號操做
  5. trap finish exit                       // 當腳本退出(異常或正常)時,執行 finish函數

函數,信號命令寫在操做以前

 

數組

索引數組:

  1. declare -a array                數組的聲明
  2. array[0]=value1 array[1]=value2 ...       數組的賦值
  3. array=( value1 value2 value3 ... )
  4. array=([0]=value1 [3]=value2 ...)
  5. read -a array          交互式方式
  6. echo ${array[0]}     數組的第一個元素的值
  7. echo ${array[*]}     數組的全部元素的值
  8. echo ${array[@]}
  9. echo ${#array[@]}   數組元素的個數
  10. array=({a..z})          調用命令給數組賦值
  11. unset array            刪除數組
  12. unset array[index]    刪除數組的某個元素
  13. declare -a               查看數組
  14. echo ${!array[@]}    查看數組的全部下標
  15. array[${#array[@]}]=value   向稠密數組中添加元素
  16. 數組的遍歷

關聯數組:

  1. declare -A ARRAY
  2. ARRAY=([index1]=value1 [index2]=value2 [index3]=value3 ...)
  3. 數組的遍歷同關聯數組同樣

數組切片:

  1. ${array[@]:offset:number}  
    1. offset 要跳過的元素個數
    2. number 要取出的元素個數
  2. ${array[@]:offset}  取偏移量以後的全部元素

腳本練習

# 磁盤使用率達到 20% 時報警
#!/bin/bash
#
declare -A DISK
WARNING=20
df |sed -rn '/^\/dev\/sd/s@^([^[:space:]]+).* ([0-9]+)%.*@\1 \2@p' > diskspace.txt
while read line;do
	index=`echo $line|cut -d' ' -f1`
	DISK[$index]=`echo $line|cut -d' ' -f2`
	if [ ${DISK[$index]} -gt $WARNING ];then
		echo -e "\033[1;31mdisk $index will be full,$index use ${DISK[$index]}%\033[0m"
	fi
done < diskspace.txt
//隨機生成10個數字,找出最大值和最小值
#!/bin/bash
#
declare -a RAND
for((i=0;i<10;i++));do
	RAND[$i]=$RANDOM
	if [ $i -eq 0 ];then
		MAX=${RAND[$i]}
		MIN=$MAX
	else
		[ ${RAND[$i]} -gt $MAX ] && { MAX=${RAND[$i]} && continue; }
		[ ${RAND[$i]} -lt $MIN ] && MIN=${RAND[$i]}
	fi
done
for index in `echo ${!RAND[@]}`;do
	echo "$index  ${RAND[$index]}"
done
echo MAX=$MAX MIN=$MIN

 

#  編寫腳本,定義一個數組,數組中的元素對應的值是/var/log目錄下全部以.log結尾
#  的文件;統計出其下標爲偶數的文件中的行數之和
#!/bin/bash
#
declare -a files
files=(/var/log/*.log)
declare -i lines
for index in `seq 0 $[${#files[@]}-1]`;do
	if [ $[$index%2] -eq 0 ];then
		let lines+=$(wc -l ${files[$index]}|cut -d ' ' -f1)
	fi
done
echo "Lines: $lines"

 

# 輸入若干個數值存入數組中,採用冒泡算法進行升序或降序排序
#!/bin/bash
declare -a bubble
num=10
for i in `eval echo {1..$num}`;do
    bubble[$i]=$RANDOM
done
echo ${bubble[@]}
                                                                                                                 
for((i=1;i<num;i++));do
    for((j=i+1;j<=num;j++));do
        if [ ${bubble[$i]} -gt ${bubble[$j]}  ];then
            min=${bubble[$j]}
            bubble[$j]=${bubble[$i]}
            bubble[$i]=$min
        fi
    done
done
for index in `echo ${!bubble[@]}`;do
    echo "$index ${bubble[$index]}"
done
echo min=${bubble[1]} max=${bubble[$num]}

 

每隔3秒鐘到系統上獲取已經登陸的用戶的信息;若是發現用戶zhangsan登陸,
則將登陸時間和主機記錄於日誌/var/log/login.log中,並退出腳本

#!/bin/bash
#
while :;do
	if who|grep ^zhangsan &>/dev/null;then
		MESSAGES=`who|grep ^zhangsan`
		TIME=$(echo $MESSAGES|awk '{print $3,$4}')
		HOST=$(echo $MESSAGES|awk '{print $NF}'|tr -d '()')
		echo "$HOST $TIME" >> /var/log/login.log
		break
	fi
	sleep 3
	who
done

 

隨機生成10之內的數字,實現猜字遊戲,提示比較大或小,相等則退出

#!/bin/bash
#
RAND=$[$RANDOM%10+1]
while :;do
	read -p "Please input a number[1-10]: " number
	if [ -z "$number" ];then
		echo "input null"
		continue
	fi
	if [[ ! $number =~ ^[0-9]+$ ]];then
		continue
	fi
	if [  $number -gt $RAND ];then
		echo "large digit"
	elif [ $number -lt $RAND ];then
		echo "small digit"
	else
		echo "ok"
		break
	fi
done

用文件名作爲參數,統計全部參數文件的總行數

#!/bin/bash
#
files=$@
if [ -z "$1" ];then
	echo "Usage:`basename $0` filename ..."
	exit
fi
for file in $files;do
	if [ -f $file ];then
		let rows+=`wc -l $file|cut -d' ' -f1`
	else
		echo "$file is not file"
	fi
done
echo $rows
相關文章
相關標籤/搜索