Linux Shell脚本编程提高(12)
该系列文章只是本人的学习笔记,文章中的文字描述提取自《Linux鸟哥私房菜》《Linux运维之道》等书中的重点内容,化繁为简能够在工作中快速复习掌握重点,并不代表个人立场,但转载请加出处,并注明参考文献。
实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核,不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序.Shel编程语言具有普通编程语言的很多特点,比如它也有循环结构和分支控制结构等,用这种编程语言编写的Shell程序与其他应用程序具有同样的效果,下面我们会介绍Shell-Script的编写.
Shell 条件判断
◆按文件类型判断◆
1.使用 [] 来执行判断,并使用echo $? 判断执行结果
[root@localhost ~]# ls
lyshark.log passwd.awk
[root@localhost ~]# [ -e ./lyshark.log ]
[root@localhost ~]# echo $? #返回0表示文件 ./lyshark.log 存在
0
[root@localhost ~]# [ -e ./shar ] #返回1表示文件 ./shar 不存在
[root@localhost ~]# echo $?
1
2.我们可以结合之前所学的 && 和 || 实现判断后输出判断结果
[root@localhost ~]# ls
lyshark.log passwd.awk
[root@localhost ~]# [ -e ./lyshark.log ] && echo "check ok" || echo "None"
check ok
[root@localhost ~]# [ -e ./shar ] && echo "check on" || echo "None"
None
◆按文件权限判断◆
1.使用 -r 判断文件是否可读,和可执行
[root@localhost ~]# ls
lyshark.log passwd.awk
[root@localhost ~]# [ -r ./lyshark.log ] && echo "check ok" || echo "None"
check ok
[root@localhost ~]# [ -x ./lyshark.log ] && echo "check ok" || echo "None"
None
[root@localhost ~]# [ -r ./lyshark.log ] && [ -x ./lyshark.log ] && echo "可读,可执行" || echo "可读,不可执行" || echo
"不可读,不可执行"
可读,不可执行
◆两文件之间的比较◆
1.通过 -ef 判断是否是相同的I节点
[root@localhost ~]# ls -li
total 0
8409155 -rw-r--r-- 2 root root 0 Sep 25 21:39 lyshark_ln.log
8409155 -rw-r--r-- 2 root root 0 Sep 25 21:39 lyshark.log
[root@localhost ~]# [ ./lyshark.log -ef lyshark_ln.log ] && echo "ok" || echo "no"
ok
◆数值之间的比较◆
1.比较两数字,大小关系
[root@localhost ~]# [ 23 -ge 24 ] && echo "23 >= 24 " || echo "23 <= 24"
23 <= 24
[root@localhost ~]# [ 30 -ge 24 ] && echo "30 >= 24 " || echo "30 <= 24"
30 >= 24
◆字符串之间的比较◆
1.字符串之间的比较例子,字符串是否为空
[root@localhost ~]# name=LyShark
[root@localhost ~]# age=""
[root@localhost ~]# unset sex
[root@localhost ~]# [ -z "$name" ] && echo "字符串空" || echo "不为空"
不为空
[root@localhost ~]# [ -z "$age" ] && echo "字符串空" || echo "不为空"
字符串空
[root@localhost ~]# [ -z "$sex" ] && echo "字符串空" || echo "不为空"
字符串空
2.两个字符串相等比较
[root@localhost ~]# x=100
[root@localhost ~]# y=200
[root@localhost ~]# z=100
[root@localhost ~]# [ "x" == "y" ] && echo "yes" || echo "no"
no
[root@localhost ~]# [ "$x" == "$y" ] && echo "yes" || echo "no"
no
[root@localhost ~]# [ "$x" == "$z" ] && echo "yes" || echo "no"
yes
◆多重条件判断◆
1.逻辑与:判断变量x不为空,并且x大于20
[root@localhost ~]# declare -i x=10
[root@localhost ~]# [ -n "$x" -a "$x" -gt 20 ] && echo "yes" || echo "no"
no
[root@localhost ~]# declare -i x=30
[root@localhost ~]# [ -n "$x" -a "$x" -gt 20 ] && echo "yes" || echo "no"
yes
2.逻辑非:判断x变量不为空,或!取反
[root@localhost ~]# declare -i x=30
[root@localhost ~]# [ -n "$x" ] && echo "yes" || echo "no"
yes
[root@localhost ~]# [ ! -n "$x" ] && echo "yes" || echo "no"
no
IF条件判断
if、then、else语句用于判断给定的条件是否满足,并根据测试条件的真假来选择相应的操作.if/else仅仅用于两分支判断,多分支的选择时需要用到if/else语句嵌套、if/elif/else和case多分支选择判断结构.
IF结构例子: 一个就简单的单分支结构.测试条件后如果没有";"则then语句要换行.
#!/bin/sh
echo "Please input a Number:"
read Num
if [ "$Num" -lt 15 ]
then
echo "$Num <= 15"
fi
IF/IF-ELSE结构: 一个双分支结构,如下执行删除文件,成功返回then是否返回else.
#!/bin/sh
echo "Please input the file which you want to delete:"
read file
if rm -f "$file"
then
echo "Delete the file $file sucessfully!"
else
echo "Delete the file $file failed!"
fi
IF/ELSE嵌套: 可同时判断三个或三个以上条件,但要注意if与else配对关系,else语句总是与它上面最近的未配对的if配对.
#!/bin/bash
#提示用户输入分数(0-100)
echo "Please Input a integer(0-100): "
read score
#判断学生的分数类别
if [ "$score" -lt 0 -o "$score" -gt 100 ]
then
echo "The score what you input is not integer or the score is not in (0-100)."
else
if [ "$score" -ge 90 ]
then
echo "The grade is A!"
else
if [ "$score" -ge 80 ]
then
echo "The grade is B!"
else
if [ "$score" -ge 70 ]
then
echo "The grade is C!"
else
if [ "$score" -ge 60 ]
then
echo "The grade is D!"
else
echo "The grade is E!"
fi
fi
fi
fi
fi
IF/ELIF/ELSE结构: if/else嵌套在编程中很容易漏掉then或fi产生错误,而且可读性很差,因此引入if/elif/else结构针对某一事件的多种情况进行处理,fi只出现一次,可读性也提高了.
#!/bin/bash
echo "Please Input a integer(0-100): "
read score
if [ "$score" -lt 0 -o "$score" -gt 100 ]
then
echo "The score what you input is not integer or the score is not in (0-100)."
elif [ "$score" -ge 90 ]
then
echo "The grade is A!"
elif [ "$score" -ge 80 ]
then
echo "The grade is B!"
elif [ "$score" -ge 70 ]
then
echo "The grade is C!"
elif [ "$score" -ge 60 ]
then
echo "The grade is D!"
else
echo "The grade is E!"
fi
实例1: 通过单分支判断磁盘是否已满.
[root@localhost ~]# cat if.sh
#!/bin/bash
ret=$( df -h | grep "/dev/sda1" | awk '{printf $5}' | cut -d "%" -f 1 )
if [ $ret -ge 80 ]
then
echo -e "/dev/sda1 is full !!"
fi
实例2: 通过多分支判断磁盘是否已满.
[root@localhost ~]# cat if.sh
#!/bin/bash
ret=$( df -h | grep "/dev/sda1" | awk '{printf $5}' | cut -d "%" -f 1 )
if [ $ret -ge 80 ]
then
echo -e "/dev/sda1 is full !"
else
echo -e "/dev/sda1 is not full !"
fi
实例3: 多分支判断小例子.
[root@localhost ~]# cat if.sh
#!/bin/bash
read -p "输入一个数字:" num
if [ "$num" -gt "100" ]
then
echo -e "这个数大于100"
elif [ "$num" -lt "100" ]
then
echo -e "这个数小于100"
elif [ "$num" -eq "100" ]
then
echo -e "这个数等于100"
fi
实例4: 判断输入的年份是否是润年(润年条件:1、能被4整除,但不能被100整除的年份.2、能被100整除,又能被400整除的年份)
#!/bin/sh
echo "Please Input a year: "
read year
let "n1=$year % 4"
let "n2=$year % 100"
let "n3=$year % 400"
if [ "$n1" -ne 0 ]
then
leap=0
elif [ "$n2" -ne 0 ]
then
leap=1
elif [ "$n3" -ne 0 ]
then
leap=0
else
leap=1
fi
CASE分支结构
case结构变量值依次比较,遇到双分号则跳到esac后的语句执行,没有匹配则脚本将执行默认值*
"后的命令,直到"';;"为止.case的匹配值必须是常量或正则表达式.
#!/bin/bash
read -p "输入一个符号:" temp
case $temp in
"-print")
echo -e "您执行了print函数"
;;
"-save")
echo -e "您执行了save函数"
;;
"-help")
echo -e "您执行了help函数"
;;
*)
echo -e "您执行了其他操作"
;;
esac
FOR循环结构
Shell编程中循环命令用于特定条件下决定某些语句重复执行的控制方式,有三种常用的循环语句:for、while和until.while循环和for循环属于"当型循环",而until属于"直到型循环",循环控制符:break和continue控制流程转向.
列表FOR循环: 循环打印数据分别从1遍历到5.
do和done之间的命令称为循环体,执行次数和list列表中常数或字符串的个数相同.for循环,首先将in后list列表的第一个常数或字符串赋值给循环变量,然后执行循环体,以此执行list,最后执行done命令后的命令序列.
#!/bin/bash
for tmp in {1..5}
do
echo "Hello, Welcome $tmp times"
done
FOR循环累加: 通过FOR循环累加打印数据.
通过i的按步数2不断递增,计算sum值为2500.同样可以使用seq命令实现按2递增来计算1~100内的所有奇数之和,for i in $(seq 1 2 100)
,seq表示起始数为1,跳跃的步数为2,结束条件值为100.
#!/bin/bash
sum=0
for i in {1..100..2}
do
let "sum+=i"
done
echo "sum=$sum"
FOR循环遍历目录: 通过for循环显示当前目录下所有的文件.
#!/bin/bash
for file in $( ls )
#for file in *
do
echo "file: $file"
done
不带列表FOR: 由用户制定参数和参数的个数,与上述的for循环列表参数功能相同.
#!/bin/bash
echo "number of arguments is $#"
echo "What you input is: "
for argument
do
echo "$argument"
done
C风格FOR循环: 也被称为计次循环.
#!/bin/bash
for((integer = 1; integer <= 5; integer++))
do
echo "$integer"
done
实例1: 通过for循环打印1-10.
[root@localhost ~]# cat for.sh
#!/bin/bash
for temp in `seq 1 10`
do
echo -e "打印数据: $temp"
done
实例2: 通过for循环计算1-100的累加和.
[root@localhost ~]# cat for.sh
#!/bin/bash
declare -i sum=0
for temp in `seq 1 100`
do
sum=$sum+$temp
done
echo -e "从1+到100的结果是: $sum"
实例3: 从列表中选择数据.
[root@localhost ~]# cat for.sh
#!/bin/bash
for temp in 1 3 5 7 9
do
echo -e "打印: $temp"
done
[root@localhost ~]# bash for.sh
打印: 1
打印: 3
打印: 5
打印: 7
打印: 9
实例4: 读取文件内容并打印.
[root@localhost ~]# cat for.sh
#!/bin/bash
world=`cat /etc/passwd`
for temp in $world
do
echo -e "打印: $temp"
done
WHILE 循环
也称为前测试循环语句,重复次数是利用一个条件来控制是否继续重复执行这个语句.为了避免死循环,必须保证循环体中包含循环出口条件即表达式存在退出状态为非0的情况.
计数控制: 指定了循环的次数500,初始化计数器值为1,不断测试循环条件i是否小于等于100.在循环条件中设置了计数器加2来计算1~100内所有的奇数之和.
#!/bin/bash
sum=0
i=1
while(( i <= 100 ))
do
let "sum+=i"
let "i += 2"
done
echo "sum=$sum"
结束标记控制的while循环: 设置一个特殊的数据值(结束标记)来结束while循环.
#!/bin/bash
echo "Please input the num(1-10) "
read num
while [[ "$num" != 4 ]]
do
if [ "$num" -lt 4 ]
then
echo "Too small. Try again!"
read num
elif [ "$num" -gt 4 ]
then
echo "To high. Try again"
read num
else
exit 0
fi
done
echo "Congratulation, you are right! "
标志控制的while循环: 使用用户输入的标志值来控制循环的结束(避免不知道循环结束标志的条件).
#!/bin/bash
echo "Please input the num "
read num
sum=0
i=1
signal=0
while [[ "$signal" -ne 1 ]]
do
if [ "$i" -eq "$num" ]
then
let "signal=1"
let "sum+=i"
echo "1+2+...+$num=$sum"
else
let "sum=sum+i"
let "i++"
fi
done
命令行控制的while循环: 使用命令行来指定输出参数和参数个数,通常与shift结合使用,shift命令使位置变量下移一位($2代替$1、$3代替$2,并使$#变量递减
),当最后一个参数显示给用户,$#
会等于0,$*
也等于空.
#!/bin/bash
echo "number of arguments is $#"
echo "What you input is: "
while [[ "$*" != "" ]]
do
echo "$1"
shift
done
while计算: 通过while循环,计算1-100的累加和.
[root@localhost ~]# cat while.sh
#!/bin/bash
declare -i x=0
declare -i num=0
while [ "$x" -lt "100" ]
do
x=$x+1
num=$num+$x
done
echo -e "从1-100结果是: $num"
[root@localhost ~]# bash while.sh
从1-100结果是: 5050
UNTIL 循环
until命令和while命令类似,while能实现的脚本until同样也可以实现,但区别是until循环的退出状态是不为0,退出状态是为0(与while刚好相反),即whie循环在条件为真时继续执行循环而until则在条件为假时执行循环.
#!/bin/bash
i=0
until [[ "$i" -gt 5 ]] #大于5
do
let "square=i*i"
echo "$i * $i = $square"
let "i++"
done
#!/bin/bash
for (( i = 1; i <=9; i++ ))
do
for (( j=1; j <= i; j++ ))
do
let "temp = i * j"
echo -n "$i*$j=$temp "
done
echo "" #output newline
done
#!/bin/bash
i=0
until [[ "$i" -gt 5 ]] #大于5
do
let "square=i*i"
echo "$i * $i = $square"
let "i++"
done
跳出语句(break,continue)
break: 在for、while和until循环中break可强行退出循环,break语句仅能退出当前的循环,如果是两层循环嵌套,则需要在外层循环中使用break.
#!/bin/bash
sum=0
for (( i=1; i <= 100; i++))
do
let "sum+=i"
if [ "$sum" -gt 1000 ]
then
echo "1+2+...+$i=$sum"
break
fi
done
continue: 在for、while和until中用于让脚本跳过其后面的语句,执行下一次循环.continue用于显示100内能被7整除的数.
#!/bin/bash
m=1
for (( i=1; i < 100; i++ ))
do
let "temp1=i%7" #被7整除
if [ "$temp1" -ne 0 ]
then
continue
fi
echo -n "$i "
let "temp2=m%7" #7个数字换一行
if [ "$temp2" -eq 0 ]
then
echo ""
fi
let "m++"
done
SELECT 语句
select结构从技术角度看不能算是循环结构,只是相似而已,它是bash的扩展结构用于交互式菜单显示,功能类似于case结构比case的交互性要好.
[root@localhost ~]# cat select.sh
#!/bin/bash
echo -e "请选择系统类型?"
select var in "Linux" "GNU HURD" "FreeBSD" "Other";
do
if [ $var == "Linux" ]
then
echo -e "您的系统是Linux"
elif [ $var == "FreeBSD" ]
then
echo -e "您的系统是FreeBSD"
fi
break
done
[root@localhost ~]# bash select.sh
请选择系统类型?
1) Linux
2) GNU HURD
3) FreeBSD
4) Other
#? 1
您的系统是Linux
#!/bin/bash
declare -a serial
serial=(1 2 3 4)
PS3="Enter a number: "
select var in "a" "b" "c" "d"
do
if ! echo ${serial[@]} | grep -q $REPLY
then
echo "please enter [1-4]."
continue
fi
echo "your anwser is: $var"
break
done
[root@localhost ~]# bash select.sh
1) a
2) b
3) c
4) d
Enter a number: 1
your anwser is: a
FUNCTION 函数
[root@localhost ~]# cat function.sh
#!/bin/bash
function my_print()
{
echo -e "------------------------"
echo -e "hello world"
echo -e "------------------------"
return "127"
}
my_print
echo $?
[root@localhost ~]# bash function.sh
------------------------
hello world
------------------------
127
参考文献:Linux鸟哥私房菜,Linux运维之道
Linux Shell脚本编程提高(12)的更多相关文章
- Linux shell脚本编程(一)
Linux shell脚本编程: 守护进程,服务进程:启动?开机时自动启动: 交互式进程:shell应用程序 广义:GUI,CLI GUI: CLI: 词法分析:命令,选项,参数 内建命令: 外部命令 ...
- Linux shell脚本编程(三)
Linux shell脚本编程 流程控制: 循环语句:for,while,until while循环: while CONDITION; do 循环体 done 进入条件:当CONDITION为“真” ...
- Linux shell脚本编程(二)
Linux shell脚本编程(二) 练习:求100以内所有偶数之和; 使用至少三种方法实现; 示例1: #!/bin/bash # declare -i sum=0 #声明一个变量求和,初始值为0 ...
- Linux Shell脚本编程--Linux特殊符号大全
Linux Shell脚本编程--Linux特殊符号大全 linux_shell 特殊符号的介绍 2011
- Linux Shell脚本编程while语句
Linux Shell脚本编程while语句案例 1,每隔3秒,打印一次系统负载 #!/bin/bash while truedo uptime sleep 3done 2,把监控结果保存 ...
- Linux shell脚本编程基础之练习篇
shell脚本编程基础之练习篇. 1.编写一个脚本使我们在写一个脚本时自动生成”#!/bin/bash”这一行和注释信息. #!/bin/bash ] then echo "请输入一个参数& ...
- Linux Shell脚本编程-基础1
概述: shell脚本在Linux系统管理员的运维工作中非常重要.shell脚本能够帮助我们很方便的管理服务器,因为我们可以指定一个任务计划,定时的去执行某一个脚本以满足我们的需求.本篇将从编程基础 ...
- 【学习】Linux Shell脚本编程
1.脚本的组成和执行 Linux shell脚本的结构并不复杂,其主要由变量.内部命令以及shell的语法结构和一些函数.其他命令行的程序等组成,以下是一个简单的shell脚本. #!/bin/bas ...
- [linux] shell脚本编程-xunsearch安装脚本学习
安装脚本setup.sh #!/bin/sh # FULL fast install/upgrade script # See help message via `--help' # $Id$ # s ...
随机推荐
- maven 介绍(zz )
Maven 编辑 目录 1简介 2特点 3常用命令 4推荐书籍 5Win7配置 6生命周期 1 1简介 Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构 ...
- 【WebService】调用第三方提供的webService服务(七)
互联网上面有很多的免费webService服务,我们可以调用这些免费的WebService服务,将一些其他网站的内容信息集成到我们的Web应用中显示,下面就以获取天气预报数据和查询国内手机号码归属地为 ...
- linux中命令突然不能用
先用:echo $PATH 发现path丢失:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 于是用临时环境变量 export ...
- lambda表达式和表达式树(深入理解c#)
1.Lambda形式 1). Lambda表达式最冗长的形式: (显式类型的参数列表)=>{语句} 2). 大多数时候,都可以用一个表达式来表示主体,该表达式的值是Lambda的结果,在这些情况 ...
- 2019.01.08 bzoj4543: [POI2014]Hotel加强版(长链剖分+dp)
传送门 代码: 长链剖分好题. 题意:给你一棵树,问树上选三个互不相同的节点,使得这个三个点两两之间距离相等的方案数. 思路: 先考虑dpdpdp. fi,jf_{i,j}fi,j表示iii子树中离 ...
- Source Routing
Source routing Followed by book_Principles and Practices of Interconnection Networks, p204. With sou ...
- 如何在MYSQL下所有指定数据库名下执行SQL
mysql下用户库比较多,都有统一的命名格式,希望在这些所有用户库执行脚本,更新数据,或者查询数据 可以采用以下存储过程实现 DROP PROCEDURE IF EXISTS `sp_execalld ...
- 阿里云存储oss+怎么上传找文件夹
最近公司做工程项目,实现文件夹云存储上传. 网上找了很久,发现网上很多项目都存在相似问题,最后终于找到了一个符合我要求的项目. 工程如下: 这里对项目的文件夹云存储上传进行分析,实现文件夹上传,如何进 ...
- AIX 批量更改密码
使用 chpasswd 可以使用 chpasswd 方便地更改单个或多个账户密码.这意味着不需要像平时一样在命令行上重复输入密码.尽管可以以交互方式使用 chpasswd,但是我建议以非交互方式使用它 ...
- 关于windows10的使用
关于windows10的使用 个人习惯设置 打开我的电脑之后,不是定位到此电脑,而是定位到快速访问. [解决办法] 用win + 箭头 快捷键将窗口靠边之后,另一边出现多个窗口 [解决办法] win ...