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
相关文章
相关标签/搜索