顺序结构
顺序结构定义
1.shell 程序流程控制结构三大结构
1)顺序结构
2)选择结构
3)循环结构
2.顺序结构的定义
顺序结构的程序设计是最简单的一种结构,它的执行顺序是自上而下,依次执行,因此,我们只要按照解决问题的思路依次编写程序即可。
顺序结构执行的流程图:
顺序结果的编写流程以及注意事项
1.顺序结构程序编写流程
1)编辑脚本文件,以#!/bin/sh 开头;
#!/bin/sh是指此脚本使用/bin/sh来解释执行,#!是特殊的表示符,其后面跟的是此解释此脚本的shell的路径。其实第一句的#!是对脚本的解释器程序路径,脚本的内容是由解释器解释的,我们可以用各种各样的解释器来写对应的脚本。
2)编写业务程序,顺序编写语句块1、语句块2、语句块3 。
2.掌握常见的系统变量的含义:
这些系统变量通常用与命令行参数的获取。
变量名 | 说明 |
---|---|
$# | 不包括命令在内的命令行参数的数目 |
$* | 命令行所有参数组成的字符串 |
$@ | 命令行所有参数组成的字符串 |
$n | n为数字,$0表示命令名称,$1表示命令第一个参数,以此类推 |
$? | 上一个命令的返回值,如果正常退出则返回0,反之为非0值 |
$$ | 当前进程的进程号 PID |
%! | 后台运行的最后一个进程的进程好PID |
注意:有时候需要获取到参数的个数,以及所有参数的内容。
使用方法:
/bin/sh analyse_server.sh $server_ip
[liu@WLJY01 ~]$ sh analyse_server.sh 192.168.1.1 192.168.1.2 192.168.1.3 .....
3.掌握常见的环境变量
这些变量与系统工作环境有关
变量名 | 说明 | 变量名 | 说明 |
---|---|---|---|
HOME | 当前用户主目录 | PWD | 用户的当前目录 |
PATH | 命令搜索路径 | UID | 当前用户标识符 |
LOGNAME | 用户登录名 | TERM | 终端的类型 |
PS1 | 第一命令提示符,是#或$ | SHELL | 用户的shell类型以及路径 |
PS2 | 第二命令提示符,默认是> | HISFILE | 存储历史命令的文件 |
4.掌握用户变量的定义和引用
用户自己定义变量的定义与引用。
理解:
a=“this is a string”
echo $a
echo ${a}
# 这两个输出的区别是什么? 没有区别
echo ${a}bc
echo $abc
# 第二个由于没有abc的变量,输出为空,不同于第一个
交互式输入与输出程序编写
1.交互式输入与输出
read 命令读取标准输入设备的一行,到新行换行符前的字符作为终止,把读到的字符赋值给变量。
可以结合echo 一起实现读取并输出的功能。
2.顺序结构 交互式输入与输出程序演练
1)程序功能,读取一个IP地址串,然后输出该IP地址。
[liu@WLJY01 myscript]$ cat read-echo.sh
#!/bin/sh
# 接受输入并输出IP地址
echo "please input your ipaddress"
read ipaddr
echo "my ip address is $ipaddr"
2) 给出输入提示的read用法
read -p “提示信息:” myaddr
[liu@WLJY01 myscript]$ cat read-echo2.sh
#!/bin/sh
# 接受输入并输出
now_time=`date +%F,%H:%M:%S`
read -p "please input your username:" username
read -p "please input password:" password
password_md5=$(echo $password|md5sum|awk '{print $1}')
echo "$now_time,系统为您生成的用户名和密码为:$username/$password_md5"
awk是用来提取列的主要工具;
{print $1}就是将某一行(一条记录)中以空格为分割符的第一个字段打印出来
echo "aa bb cc" | awk -F '{print $1}'
#结果就是aa,意思是把字符串按空格分割,取第一个
选择结构
选择结构的定义
1.选择结构的定义
选择结构是程序中带有判断的一种逻辑结构,只有符合一定的条件,程序体才会被执行。
2.Linux shell 选择结构分类
1)if-then控制结构
2)case–esac控制结构
if then 控制结构
1.if then 控制结构的分类
1.单分支if结构,此类单分支结构,当条件满足的时候,就会执行then后面的语句,不满足就直接退出判断语句。
if [ 条件 ];then
语句...
fi
程序演练,判断一个用户是否存在,存在则输出这个用户存在信息。
#!/bin/sh
#if-then 单分支控制结构演练
id apache # 查找id为apache的用户信息
if [$? -eq 0] #查找是否成功
then
echo "apache user exists!"
fi
[liu@WLJY01 myscript]$ cat if-then-dan.sh
[root@WLJY01 myscript]# sh if-then-dan.sh apache
uid=48(apache) gid=48(apache) groups=48(apache)
apache user exists!
2.双分支if结构,当条件满足的时候就会运行then后面的语句,条件不满足的时候就运行else后面的语句。
语法:
if [ 条件 ];then
语句1...
else
语句2...
fi
程序演练:判断第一个系统参数用户是否存在,存在则输出用户的UID ,否则创建该用户,并且输出这个用户的UID。
#!/bin/sh
#if-then双分支结构演练
id=$(id -u $1) #显示用户信息,第一个参数$1是用户名称,结果引用传给id变量
if [$? -eq 0]
then
#存在该用户,输出他的id
echo "$1 user already exist,uid is $id"
else
#不存在这个用户,则创建这个用户
useradd $1
id=$(id -u $1)
echo "$1 user already exist,uid is $id"
fi
[root@WLJY01 myscript]# cat if-then-shuang.sh
[root@WLJY01 myscript]# sh if-then-shuang.sh liutao
liutao user already exist , uid is 503
3.嵌套if结构,当条件满足条件1,则执行then后面的语句,当条件再满足条件2,则执行then后面的语句,不满足条件2,则退出;当条件不满足条件1,则执行else后面的语句。
if [ 条件1 ];then
if [ 条件2 ];then
语句...
else
语句.....
fi
else
语句....
fi
程序演练:首先判断运行脚本的系统参数有多少个,如果参数个数不等于1,则提示参数输入错误,否则,判断输入的用户是否存在,存在则输出用户的UID ,不存在,则创建该用户,并且输出这个用户的UID。
#!/bin/sh
#if-then嵌套结构演练
#Usage:sciptfile username
if [$# -ne 1] #如果输入的参数个数不等于1
then
echo "参数输入错误,只能输入一个参数"
else
id=$(id -u $1) # $()跟``一样,都是执行小括号内的Linux命令
if [$? -eq 0]
then
#存在该用户,输出他的id
echo "$1 user already exist,uid is $id"
else
#不存在这个用户,则创建这个用户
useradd $1
id=$(id -u $1)
echo "$1 user already exist,uid is $id"
fi
fi
[root@WLJY01 myscript]# sh if-then-qiantao.sh liutao
liutao user already exist , uid is 503
[root@WLJY01 myscript]# sh if-then-qiantao.sh liutao5
id: liutao5: No such user
liutao5 is created ,and uid is 506
case esac控制结构
case语句适用于需要进行多重分支的应用情况,它也是选择结构中常用的一种控制结构。
case分支语句的格式如下:
case $变量名 in # 严格掌握其语法
模式1) # 右括号不能省
命令序列1
;; # 两分号不能省
模式2)
命令序列2
;;
*)
默认执行的命令序列
;;
esac #结尾反写case表示结束。
程序演练:
用户从键盘输入一个字符,判断该字符是字母、数字、还是其他字符,并给出其提示信息。
#!/bin/sh
#case-case分支结构演练
read -p "请输入一个字符,然后按回车" key
#先显示提示符,然后将用户输入的内容赋值给key变量
case $key in
[0-9])
echo "你输入的是数字"
echo "数字是:$key"
;;
[a-z][A-Z])
echo "你输入的是字符"
echo "字符是:$key"
;;
*)
echo "你输入的是特殊符号"
echo "特殊符号是:$key"
;;
esac
[liu@WLJY01 myscript]$ cat case_1.sh
[liu@WLJY01 myscript]$ sh case_1.sh
请输入一个字符,然后按回车3
你输入的是数字
数字是:3
[liu@WLJY01 myscript]$ sh case_1.sh
输入一个字符,然后按回车R
你输入的是字符
字符是:R
[liu@WLJY01 myscript]$ sh case_1.sh
请输入一个字符,然后按回车%
你输入的是特殊符号
特殊符号是:%
循环结构
for循环结构
for 循环结构分类:
for 循环结构与c语言的循环结构类似,分为如下几种:
1.编历/列表式循环结构
语法如下:
for variable in list
do
statement
Done
实际环境操作:
1)用seq产生一个序列范围,来控制编历的次数。
(seq命令产生一个数到另一个数之间的所有整数) seq 10 20
#/bin/sh
#演练for循环之遍历列表结构用法
for i in $(seq 3) #连续序列
#for i in $(seq 1 3)
do
echo "output $i ..."
done
[liu@WLJY01 myscript]$ ls for_1_1.sh
[liutaostdio@WLJY01 myscript]$ sh for_1_1.sh
output 1 ...
output 2 ...
output 3 ...
2)命令序列不是连续的情况,可以自定义来处理。
#!/bin/sh
#演练for循环之遍历列表结构用法
for mydir in A B C E J #非连续序列
do
mkdir -v $mydir # -v 为每个目录显示提示信息。
chmod 755 $mydir
done
[liutaostdio@WLJY01 myscript]$ sh for_1_2.sh
mkdir: created directory `A'
mkdir: created directory `E'
mkdir: created directory `J'
2.C语言风格的循环结构
当for循环的条件为真时,执行循环体中的语句,语法如下:
for (( expr1;expr2;expr3 )) # (()),注意
do
statement
done
创建一年中1月至12月所使用的数据库,将调用统计的结果插入到相应的月份中 。
#!/bin/sh
#演练C程序式的for循环结构
#提前创建一年中1月-12月所使用的数据库,将调用统计的结果插入到相应的月份中。
for ((month=1;$month<=12;month++))
do
echo "create database analyse_$month..."
sleep 1 #停顿1秒
#mysql -e "create database analyse_$month"
#统计结果入相应的月份库中
#...
done
[liutaostdio@WLJY01 myscript]$ sh for_2_1.sh
create database analyse_1...
create database analyse_2...
create database analyse_3...
create database analyse_4...
While循环结构
1.while循环的结构
当while 条件表达式为真时,执行循环体中的语句,语法如下:
while expression
do
statement
done
2.while 循环控制结构又分为两种
1.while [] 结构,此时注意while 后要跟空格,否则会报错。
如: while [ $i -le 10 ],while(())结构,不用跟空格,如:while((i<10))
1)用while [] 结构控制循环的次数,输出相关的变量
#!/bin/sh
#演练while []循环结构
i=1
while [ $i -le 10] #注意[]前的空格,i<=10
do
echo $i
let i++;
done
[liu@WLJY01 myscript]$ sh while_1_1.sh
1
2
3
.....
2)用while(())结构控制循环的次数,输出相关的变量
#!/bin/sh
#演练while []循环结构
i=1
while((i<=10)) #注意(()前可以不加空格
do
echo $i
let i++;
done
[liu@WLJY01 myscript]$ sh while_1_2.sh
1
2
3
...
注意这两种语法的用法,选择好其中一种用法就可以。
3)用while循环实现一个无限循环,每隔3秒钟调用一次程序,在解决队列一类的问题的时候会经常用到。
#!/bin/sh
#演练while [ 1 ] 永久循环结构
while [ 1 ] #数字没有要求,表示为真即可
do
echo "the script is running..."
sleep 3
done
[liutaostdio@WLJY01 myscript]$ sh while_1_3.sh
the script is running..
the script is running..
the script is running..
continue 、break 使用
1.循环中有两种类型的控制break和continue
这是一种无条件的流程控制,强制程序跳出当前的循环,或跳出当前循环继续执行下一个循环。
break命令,会退出当前的循环并且将控制权传递到本循环后面的第一个命令。
continue命令,当在程序执行过程中遇到这个命令,就会忽略本次循环中剩余的命令,将控制权交给循环的顶部。
2.break 程序演示
循环从键盘读入一个字符,输出该字符,当输入的字符为’x’或‘X’时,退出当前循环。
#!/bin/sh
#演练break循环控制流程
while [ 1 ]
do
read -p "请输入一个字符:" key
test $key=x -o $key=X #是x或X
if [ $? -eq 0]
then
echo "您输入的是x或X,跳出循环..."
else
echo $key
fi
done
[liutaostdio@WLJY01 myscript]$ sh while_break_1.sh
请输入一个字符:a
请输入一个字符:1
请输入一个字符:x
您输入的是x或X,跳出循环..
3.continue 程序演示
循环从键盘读入一个字符,输出该字符,当输入的字符为’x’或‘X’时,不显示这个字符,进行下一个循环。
#!/bin/sh
#演练continue循环控制流程
while [ 1 ]
do
read -p "请输入一个字符:" key
test $key=x -o $key=X #是x或X
if [ $? -eq 0]
then
echo "您输入的是x或X,进行下一个循环..."
continue
echo "...$key..." #注意观察这里会不会输出!!!
else
echo $key
fi
done
[liutaostdio@WLJY01 myscript]$ sh while_continue_1.sh
请输入一个字符:a
请输入一个字符:b
请输入一个字符:x
您输入的是x或X,进行下一个循环...
请输入一个字符:X
您输入的是x或X,进行下一个循环...
while read 循环使用
1.while read line 可以按行读入
一直到所有行都读完,才退出循环,在实际工作中,会经常采用这种循环结构,进行数据的处理。
语法格式:
cat file.txt |while read line
# line可以换个名字,此处的cat也可以是一个产生若干行的命令,如 find
do
….
done
2.程序演练
循环读入一个文件的所有行,每行按照某种格式输出这行的第一个字段和第二个字段。
#!/bin/sh
#while read line 按行循环读取文件演练
sum_line=0
cat ./ip.txt |while read ipline
do
let sum_line++
echo -n "第$sum_line行..."
from=`echo $ipline |awk '{print $1}'` #取每行的第1个字段
ip=`echo $ipline |awk '{print $2}'` #取每行的第2个字段
echo "$from-------$ip"
sleep 1
done
echo "这个文件的行数为:$sum_line"
[liutaostdio@WLJY01 myscript]$ sh while_read_line.sh
第1行.....上海---------123.124.31.3
第2行.....北京---------175.24.211.8
第3行.....南京---------211.103.156.1
第4行.....广州---------123.124.53.12
这个文件的行数为:0 ???
需要注意的是while read line循环体中的变量,退出当前循环后,会被销毁,所以若要二次使用循环体中的变量,则需要采用其他办法。
因为管道后的while loop是sub shell ,所以里面的变量在执行完成后,需要销毁。