shell/02-Shell 流程控制_函数编程.md

1233 lines
27 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 02-Shell流程控制-函数
## 一、Shell 编程之条件结构
### 0、走在测试之前--认识各种括号
**[]**、()、{}、(())、[[]]、**$(())、$[]、$()、${}**
#### 1.单括号[] () {}
```txt
[] test命令的另一种写法
() 重新开一个子shell然后执行里面的最后一个命令可以不用分号
{} 在当前 shell 执行,里面的最后一个命令要用分号,第一个命令和左括号之间必须有一个空格
```
()和{}里的某个命令的重定向只影响该命令, 而括号外的重定向则影响到括号里的所有命令。
**()测试示例**
```bash
# 测试数据定义
[root@qfedu.com ~]# var=test
# 子shell中执行命令
[root@qfedu.com ~]# echo $var
test
[root@qfedu.com ~]# (var=notest;echo $var)
notest
[root@qfedu.com ~]# echo $var
test
# 里的执行完毕后没有改变当前shell变量的值说明在子shell中执行的
```
**{}测试示例**
```bash
[root@qfedu.com ~]# {var=notest;echo $var}
{var=notest: command not found
test}
[root@qfedu.com ~]# {var=notest;echo $var;}
-su: syntax error near unexpected token `}'
[root@qfedu.com ~]# { var=notest;echo $var;}
notest
[root@qfedu.com ~]# echo $var
notest
# {}修改了变量的值。表明在当前shell中运行的
适用场景
# { ls;pwd;}>a.txt # 对比一下下面的输出有何不同
# ls;pwd>a.txt
```
**[]测试示例-见test命令详解**
#### 2.双括号(()) [[]]
(()) 适合数值比较、运算 C语言形式
```bash
[root@wing tmp]# a=8
[root@wing tmp]# b=9
[root@wing tmp]# ((c=a+b))
[root@wing tmp]# echo $c
17
[root@wing tmp]# ((a>b))
[root@wing tmp]# echo $?
1
[root@wing tmp]# ((a<b))
[root@wing tmp]# echo $?
0
```
[[]] 适合条件测试,支持正则
#### 3.$修饰的括号
$(())、$[]、$()、${}
```shell
$(())、$[] 用途一致,用来作整数运算
$() 命令替换,等同反引号``Shell会先执行括号内的cmd然后将结果输出
${} Shell中变量的原形用于限定变量名称的范围并且支持通配符
# $(( ))还可以作不同进制(如二进制、八进位、十六进制)运算,只是输出结果皆为十进制而已。
# 16进位转十进制
[root@qfedu.com ~]# echo $((16#2a))
42
# 2进制转十进制
[root@server test]# echo $((2#11))
3
```
### 1、Shell 条件测试方法
| 方法 | 描述 |
| ---------------- | ------------------------------------------------------------ |
| test 测试表达式 | 利用test命令进行条件测试表达式test命令与测试表达式之间至少有一个空格 |
| [ 测试表达式 ] | 通过[ ]中括号进行条件测试表达式,[]中括号边界与测试表达式之间至少有一个空格 |
| [[ 测试表达式 ]] | 通过[[ ]]双中括号进行条件测试表达式,[[ ]]双中括号与测试表达式之间至少有一个空格 |
| ((测试表达式)) | 通过(( ))双小括号进行条件测试表达式,( ))双小括号两端不需要空格,常用于整数对比 |
### 2、test测试
#### 1.文件操作符
**语法**
```bash
# test 操作符 文件或目录
或者
# [ 操作符 文件或目录 ]
```
| 操作符 | 描述 |
| ----------- | -------------------------------------------------- |
| **-d 文件** | 文件存在且为目录则为真 |
| **-f 文件** | 文件存在且为普通文件则为真 |
| **-e 文件** | 文件存在则为真,不辩别是目录还是文件 |
| **-s 文件** | 文件存在且文件大小不为0则为真 |
| **-r 文件** | 文件存在且可读则为真,与执行脚本的用户权限也有关 |
| **-w 文件** | 文件存在且可写则为真,与执行脚本的用户权限也有关 |
| **-x 文件** | 文件存在且可执行则为真,与执行脚本的用户权限也有关 |
| -L 文件 | 文件存在且为链接文件则为真 |
| f1 -nt f2 | 文件f1比文件f2新则为真根据文件的修改时间计算 |
| f1 -ot f2 | 文件f1比文件f2旧则为真根据文件的修改时间计算 |
**示例**
```shell
[root@qfedu.com ~]# test -d /home
[root@qfedu.com ~]# echo $?
0
[root@qfedu.com ~]# test -d /home11111
[root@qfedu.com ~]# echo $?
1
[root@qfedu.com ~]# [ -d /home ]
[root@qfedu.com ~]# [ ! -d /ccc ] && mkdir /ccc
[root@qfedu.com ~]# [ -d /ccc ] || mkdir /ccc
```
#### 2.字符串操作符
| 参数 | 示例 | 功能 |
| --------- | ------ | -------------------------------------------- |
| **-z** | s1 | 如果字符串s1的长度为0则测试条件为真 |
| **-n** | s1 | 如果字符串s1的长度大于0则测试条件为真 |
| | s1 | 如果字符串s1不是空字符串则测试条件为真 |
| **=或==** | s1=s2 | 如果s1等于s2则测试条件为真,“=”前后应有空格 |
| **!=** | s1!=s2 | 如果s1不等于s2则测试条件为真 |
| < | s1<s2 | 如果按字典顺序s1在s2之前则测试条件为真 |
| > | s1>s2 | 如果按自定顺序s1在s2之后则测试条件为真 |
**示例**
```shell
# 字符串比较必须使用双引号
[root@qfedu.com ~]# [ "$USER" = "root" ];echo $?
0
[root@qfedu.com ~]# [ "$USER" == "root" ];echo $?
0
[root@qfedu.com ~]# BBB=""
[root@qfedu.com ~]# echo ${#BBB}
0
[root@qfedu.com ~]# [ -z "$BBB" ] # 字符长度是为0
[root@qfedu.com ~]# echo $?
0
[root@qfedu.com ~]# [ -n "$BBB" ] # 字符长度不为0
[root@qfedu.com ~]# echo $?
1
[root@qfedu.com ~]# var1=111
[root@qfedu.com ~]# var2=
[root@qfedu.com ~]# # var3变量没有定义
[root@qfedu.com ~]# echo ${#var1}
3
[root@qfedu.com ~]# echo ${#var2}
0
[root@qfedu.com ~]# echo ${#var3}
0
[root@qfedu.com ~]# [ -z "$var1" ];echo $?
1
[root@qfedu.com ~]# [ -z "$var2" ];echo $?
0
[root@qfedu.com ~]# [ -z "$var3" ];echo $?
0
[root@qfedu.com ~]# [ -n "$var1" ];echo $?
0
[root@qfedu.com ~]# [ -n "$var2" ];echo $?
1
[root@qfedu.com ~]# [ -n "$var3" ];echo $?
1
```
#### 3.整数操作符
| **在[]和test中使用** | **在[[ ]]和(( ))中使用** | **说明** |
| -------------------- | ------------------------ | -------------------------------- |
| -eq | ==或= | 等于全拼为equal |
| -ne | != | 不等于全拼为not equal |
| -gt | > | 大于全拼为greater than |
| -ge | >= | 大于等于全拼为greater or equal |
| -lt | < | 小于全拼为less than |
| -le | <= | 小于等于全拼为less or equal |
1、判断变量是不是数字
```shell
[root@qfedu.com ~]# num10=123
[root@qfedu.com ~]# num20=ssss1114ss
[root@qfedu.com ~]# [[ "$num10" =~ ^[0-9]+$ ]];echo $?
0
[root@qfedu.com ~]# [[ "$num20" =~ ^[0-9]+$ ]];echo $?
1
```
2、数值比较 [ 整数1 操作符 整数2 ]
```shell
[root@qfedu.com ~]# disk_use=$(df -P |grep '/$' |awk '{print $5}' |awk -F% '{print $1}')
[root@qfedu.com ~]# [ $disk_use -gt 90 ] && echo "war......"
[root@qfedu.com ~]# [ $disk_use -gt 60 ] && echo "war......"
war......
[root@qfedu.com ~]# id -u
0
[root@qfedu.com ~]# [ $(id -u) -eq 0 ] && echo "当前是超级用户"
当前是超级用户
[alice@qfedu.com ~]$ [ $UID -eq 0 ] && echo "当前是超级用户" || echo "you不是超级用户"
you不是超级用户
```
3、C语言风格的数值比较
```shell
[root@qfedu.com ~]# ((1<2));echo $?
0
[root@qfedu.com ~]# ((1==2));echo $?
1
[root@qfedu.com ~]# ((1>2));echo $?
1
[root@qfedu.com ~]# ((1>=2));echo $?
1
[root@qfedu.com ~]# ((1<=2));echo $?
0
[root@qfedu.com ~]# ((1!=2));echo $?
0
[root@qfedu.com ~]# ((`id -u`>0));echo $?
1
[root@qfedu.com ~]# (($UID==0));echo $?
0
```
#### 4.逻辑操作符
| **在[]和test中使用** | **在[[ ]]和(( ))中使用** | **说明** |
| -------------------- | ------------------------ | ---------------------------------- |
| -a | && | and两端都为真则结果为真 |
| -o | \|\| | or两端有一个为真则结果为真 |
| ! | ! | not两端相反则结果为真 |
```shell
[root@qfedu.com ~]# [ 1 -lt 2 -a 5 -gt 10 ];echo $?
1
1 0
[root@qfedu.com ~]# [ 1 -lt 2 -o 5 -gt 10 ];echo $?
0
[root@qfedu.com ~]# [[ 1 -lt 2 && 5 -gt 10 ]];echo $?
1
[root@qfedu.com ~]# [[ 1 -lt 2 || 5 -gt 10 ]];echo $?
0
```
#### 5、测试表达式区别总结
| **测试表达式符号** | **test** | **[ ]** | **[[ ]]** | **(( ))** |
| ------------------ | ---------------------------- | ---------------------------- | ------------------------------------------------- | ------------------- |
| 边界是否需要空格 | 需要 | 需要 | 需要 | 不需要 |
| 逻辑操作符 | !、-a、 -o | !、-a、 -o | !、&&、\|\| | !、&&、\|\| |
| 整数比较操作符 | -eq、-ne、-lt、-gt、-ge、-le | -eq、-ne、-lt、-gt、-ge、-le | -eq、-ne、-lt、-gt、-ge、-le或=、!=、<、>、>=、<= | =、!=、<、>、>=、<= |
| 字符串比较操作符 | =、==、!= | =、==、!= | =、==、!= | =、==、!= |
| 是否支持正则 | 不支持 | 不支持 | 支持 | 不支持 |
变量为空或未定义长度都为0
```shell
[root@qfedu.com ~]# [ "$USER" = "root" ];echo $?
0
[root@qfedu.com ~]# [ "$USER" = "alice" ];echo $?
1
[root@qfedu.com ~]# [ "$USER" != "alice" ];echo $?
0
[root@qfedu.com ~]# [ "$USER" = "root" ];echo $?
0
[root@qfedu.com ~]# [ "$USER" =~ ^r ];echo $?
bash: [: =~: binary operator expected
2
[root@qfedu.com ~]# [[ "$USER" =~ ^r ]];echo $? # 使用正则
0
```
### 3、Shell 分支if语句
#### 1、单分支 IF 条件语句
```shell
if [ 条件判断式 ];then
条件成立时,执行的程序
fi
# if语句使用fi结尾和一般语言使用大括号结尾不同
# [条件判断式] 就是使用test命令判断,所以中括号和条件判断式之间必须有空格
# then 后面跟符号条件之后执行的程序,可以放在[]之后,用";"分割。也可以换行写入,就不需要";"了
```
#### 2、双分支语句
```shell
if [ 条件判断式 ]then
条件成立时,执行的程序
else
条件不成立时,执行的另一个程序
fi
```
#### 3、多分支语句
```shell
if [ 条件判断式1 ]
then
当条件判断式1成立时执行程序1
elif [ 条件判断式2 ]
then
当条件判断式2成立时执行程序2
...省略更多条件....
else
当所有条件都不成立,最后执行此程序
fi
```
### 4、Shell 分支case语句
```bash
case $变量名 in
值1
如果变量的值等于值1则执行指令1
;;
值2
如果变量的值等于值2则执行指令2
;;
值3
如果变量的值等于值3则执行指令3
;;
*
如果变量的值不等于以上列出的任何值则执行默认指令
esac
```
## 二、Shell 编程之循环结构
### 1、Shell 循环 for 语句
for循环的运作方式是将串行的元素一一取出依序放入指定的变量中然后重复执行含括的命令区域在do和done 之间),直到所有元素取尽为止。
其中,串行是一些字符串的组合,彼此用$IFS所定义的分隔符如空格符隔开这些字符串称为字段。
```shell
for 变量 in 值集合
do
执行命令
done
```
- for 每次从值集合中取一个值赋值给变量
- do - done 将赋值后的变量带入执行的命令得到执行结果
- 重复以上两个步骤,直到值集合中的值被一一获取赋值给变量的到所有结果,循环结束
```bash
使用变量
num=8
for i in $(seq 2 $num)
do
echo $i
done
for i in {2..8}
```
```bash
for((i=1;i<=10;i++))
do
echo $i
done
i=1 初始化i的值为1
i<=10 比较条件
i++ 步长 每次加1
嵌套的
for((i=1;i<=10;i++))
do
for((i=1;i<=10;i++))
do
echo $i
done
echo $i
done
```
### 2、Shell 循环 while 语句
1、while 循环语法
```shell
while 条件测试
do
执行命令
done
```
- while 首先进行条件测试如果传回值为0条件测试为真则进入循环执行命令区域否则不进入循环
- 满足 while 测试条件,执行命令区域,直到 while 的测试条件不满足结束执行while循环如果条件一直满足执行无穷循环
### 3、Shell 循环 until 语句
while循环的条件测试是测真值until循环则是测假值。
```shell
until 条件测试
do
执行命令
done
```
- until 条件测试结果为假传回值不为0就进入循环。
- 条件测试不满足,执行命令区域。直到 until 条件满足结束执行until 循环(如果条件一直不满足则执行无穷循环)。
```shell
#!/bin/bash
until ((i>10)) # 条件测试只要i值未超过10就进入循环
do
let sum+=i # sum+=i和sum=sum+i是一样的sum累加上i
let ++i # i的值递增1此行是改变条件测试的命令一旦i大于10可终止循环
done # 遇到done回到 until条件测试
echo $sum # 直到 until 的条件满足显示sum的值
```
```shell
#!/bin/bash
a=1
b=1
until ((a>9)) # 条件测试只要a值未超过9就进入循环一旦超过9就不执行until和while条件相反条件真就done结束
do
until ((b>a)) # b>a,一旦b大于a就不执行
do
let "c=a*b"
echo -n "$a*$b=$c "
let b++
done
let a++
let b=1
echo ""
done
```
### 4、Shell 循环控制
breakcontinueexit 一般用于循环结构中控制循环的走向。
break和continue只能用在循环里面
exit可以用于脚本的任何地方
| **命令** | **说明** |
| ----------- | ------------------------------------------------------------ |
| break n | n 表示跳出循环的次数,如果省略 n 表示跳出整个循环 |
| continue n | n 表示退到第n层继续循环如果省略n表示跳过本次循环进入下一次循环 |
| exit n | 退出当前的shell程序并返回 nn 也可以省略 |
| return | 用于返回一个退出值给调用的函数 |
| shift | 用于将参数列表list左移指定次数最左端的那个参数就从列表中删除其后边的参数继续进入循环 |
break[N]提前结束第N层循环最内层为第1层
```bash
while CONDITION1; do
CMD1
...
if CONDITION2; then
break
fi
CMDn
...
done
```
break结束本次循环整个退出脚本
```shell
[root@qfedu.com ~]#vim test.sh
#!/bin/bash
for i in {1..10}
do
[ $i -eq 5 ] && break
echo i=$i
sleep 0.5
done
echo test is finished
[root@qfedu.com ~]#chmod +x test.sh
[root@qfedu.com ~]#./test.sh
i=1
i=2
i=3
i=4
test is finished
[root@localhost ~]# cat break1.sh
#!/bin/bash
for((i=0;i<=5;i++))
do
if [ $i -eq 3 ];then
break;
fi
echo $i
done
echo "ok"
# 运行结果为:
[root@localhost ~]# bash break1.sh
0
1
2
ok
```
continue [N]提前结束第N层的本轮循环而直接进入下一轮判断最内层为第1层
```bash
while CONDITION1;do
CMD1
...
if CONDITION2; then
continue
fi
CMDn
...
done
```
```shell
[root@localhost ~]# cat continue.sh
#!/bin/bash
for((i=0;i<=5;i++))
do
if [ $i -eq 3 ];then
continue;
fi
echo $i
done
echo "ok"
#运行结果为:
[root@localhost ~]# bash continue.sh
0
1
2
4
5
ok
[root@qfedu.com ~]#vim test.sh
#!/bin/bash
for i in {1..10}
do
[ $i -eq 5 ] && continue
echo i=$i
sleep 0.5
done
echo test is finished
[root@qfedu.com ~]#./test.sh
i=1
i=2
i=3
i=4
i=6
i=7
i=8
i=9
i=10
test is finished
```
exit 指令
```shell
[root@localhost ~]# cat exit.sh
#!/bin/bash
for((i=0;i<=5;i++))
do
if [ $i -eq 3 ];then
exit
fi
echo $i
done
echo "ok"
#运行结果为:
[root@localhost ~]# bash exit.sh
0
1
2
```
### 5、shift 指令(了解)
shift 命令用于将参数列表 list 左移指定次数,最左端的那个参数就从列表中删除,其后边的参数继续进入循环。
shift[N]:用于将参量列表 list 左移指定次数,缺省为左移一次。
参量列表 list 一旦被移动,最左端的那个参数就从列表中删 除。while 循环遍历位置参量列表时,常用到 shift
实例
```shell
[root@qfedu.com ~]# vim demo.sh
#!/bin/bash
while [ $# -gt 0 ]
do
echo $*
shift
done
[root@qfedu.com ~]# ./demo.sh a b c d e f g h
a b c d e f g h
b c d e f g h
c d e f g h
d e f g h
e f g h
f g h
g h
h
[root@qfedu.com ~]# vim shift.sh
#!/bin/bash
until [ -z "$1" ]
do
echo "$1"
shift
done
echo
[root@qfedu.com ~]# ./shift.sh a b c d e f g h
a
b
c
d
e
f
g
```
## 三、Shell 编程之函数
Shell 函数的本质是一段可以重复使用的脚本代码,这段代码被提前编写好了,放在了指定的位置,使用时直接调取即可
### 1、定义函数
可以带function fun() 定义也可以直接fun() 定义,不带任何参数。
```php
# 方法一
function name() {
commands
[return value]
}
# 方法二
name() {
commands
[return value]
}
```
- function 是 Shell 中的关键字,专门用来定义函数;
- name 是函数名;
- commands 是函数要执行的代码,也就是一组语句;
- return value 表示函数的返回值,其中 return 是 Shell 关键字,专门用在函数中返回一个值;这一部分可以写也可以不写。
- 由 { } 包围的部分称为函数体,调用一个函数,实际上就是执行函数体中的代码。
- 函数的优势
- 方便n次使用减少代码量使之方便整洁。
- 当需要修改里面的重复代码时,只需要修改一次函数即可实现需求;
- 将函数写进文件,需要时直接通过文件调用
### 2、调用函数
1、执行不带参数的函数
直接输入函数名即可,不需要带括号,
```undefined
functionName
```
- 执行函数时函数名前的关键字function和函数名后面的()均不需要带
- 函数的定义必须要在执行的程序前定义或加载
2、执行带参数的函数
```undefined
functionName arg1 arg2
```
- Shell中的位置参数($1/$2.../$#/$?/$@)均可以做为函数的参数进行传递
- $0比较特殊仍然是父脚本的名称
- 此时父脚本的参数会临时被函数的参数所掩盖或隐藏
- 函数的参数变量是在函数体内里面进行定义
调用函数示例
```shell
[root@qfedu.com ~]# cat testfunction.sh
#!/bin/bash
# first function
function HelloWorld() {
echo "Hello world"
}
# second function
Welcome() {
echo "Welcome to qfedu"
}
# third function
function HelloShell {
echo "Hello Shell"
}
# file functions
HelloWorld # 调用函数
Welcome
HelloShell
[root@qfedu.com ~]# bash testfunction.sh
Hello world
Welcome to qfedu
Hello Shell
```
从文件中调用函数示例
```shell
[root@qfedu.com ~]# cat filefunction.sh
function Sum () {
for((i=1;i<=100;i++))
do
((sum=sum+i))
done
echo '{1..100} sum is :' $sum
}
[root@qfedu.com ~]# cat filefunctionfromfile.sh
#!/bin/bash
path="/root/Test/filefunction.sh"
if [ -f ${path} ]
then
source $path # 加载函数
Sum # 调用函数
else
echo "file not exist or error"
fi
[root@qfedu.com ~]# bash filefunctionfromfile.sh
{1..100} sum is : 5050
```
函数参数传递示例
```shell
[root@qfedu.com ~]# cat functionwithargs.sh
#!/bin/bash
function Add () { # 定义函数
((sum=$1+$2))
echo "$1 + $2 sum is" ${sum}
}
Add $1 $2 # 调用函数并传递参数
[root@qfedu.com ~]# bash functionwithargs.sh 100 150
100 + 150 sum is 250
[root@qfedu.com ~]# bash functionwithargs.sh 509 150
509 + 150 sum is 659
```
### 3、return 返回函数结果
注意return的数字必须是数字用引号包裹也一样
```shell
[root@qfedu.com ~]# cat functionwithreturn.sh
#!/bin/bash
function TestReturn() {
if [ -d $1 ];then
return "122"
else
return "222"
fi
}
TestReturn $1
result=$? # 获取函数返回值
if [ ${result} == "122" ]
then
echo "$1 exist ,return value is:" ${result}
else
echo "$1 not exist ,return value is:" ${result}
fi
[root@qfedu.com ~]# bash functionwithreturn.sh /etc/sysconfiggg
/etc/sysconfiggg not exist ,return value is: 222
[root@qfedu.com ~]# bash functionwithreturn.sh /etc/sysconfig
/etc/sysconfig exist ,return value is: 122
```
在该示例中,主要通过 $? 获取返回值,但返回值的范围只能是 0~255
### 4、echo 返回函数结果
```shell
[root@qfedu.com ~]# cat functionwithecho.sh
#!/bin/bash
function TestReturn() {
if [ -d $1 ];then
echo "122"
else
echo "222"
fi
}
result=$(TestReturn $1) # 获取函数返回值
if [ ${result} == "122" ];then
echo "$1 exist ,return value is:" ${result}
else
echo "$1 not exist ,return value is:" ${result}
fi
[root@qfedu.com ~]# bash functionwithecho.sh /etc/sysconfig
/etc/sysconfig exist ,return value is: 122
[root@qfedu.com ~]# bash functionwithecho.sh /etc/sysconfiggg
/etc/sysconfiggg not exist ,return value is: 222
```
该示例中,主要使用 $() 获取返回值,在该方法中,没有范围限制,是一种比较安全的返回方式。
```shell
[root@qfedu.com ~]# cat functionwithecho.sh
#!/bin/bash
function TestReturn() {
if [ -d $1 ]
then
echo "$1 exist"
else
echo "$1 not exist"
fi
}
result=$(TestReturn $1) # 获取返回值,返回的结果是字符串
if [ "${result}" == "$1 exist" ]
then
echo "$1 exist ,return value is:" ${result}
else
echo "$1 not exist ,return value is:" ${result}
fi
[root@qfedu.com ~]# bash functionwithecho.sh /etc/sysconfiggg
/etc/sysconfiggg not exist ,return value is: /etc/sysconfiggg not exist
[root@qfedu.com ~]# bash functionwithecho.sh /etc/sysconfig
/etc/sysconfig exist ,return value is: /etc/sysconfig exist
```
### 5、全局变量和局部变量
全局变量在shell 脚本中任何地方都能使用;局部变量在函数内部使用,声明前加一个 local 就好
```bash
[root@qfedu.com ~]# cat test3.sh
function fun() {
a=$[ $b + 5 ]
c=$[ $a * 2 ]
}
a=4
b=6
fun
if [ $a -gt $b ]
then
echo "$a is larger than $b"
else
echo "$a is smaller than $b"
fi
function fun() {
local a=$[ $b + 5 ]
c=$[ $a * 2 ]
}
a=4
b=6
fun
if [ $a -gt $b ]
then
echo "$a is larger than $b"
else
echo "$a is smaller than $b"
fi
[root@qfedu.com ~]# bash test3.sh
11 is larger than 6
4 is smaller than 6
```
### 6、递归函数纯了解
```bash
[root@qfedu.com ~]# cat test6.sh
function factorial() {
if [ $1 -eq 1 ]
then
echo 1
else
local temp=$[ $1 - 1 ]
local result=$(factorial $temp)
echo $[ $result * $1 ]
fi
}
read -p "Enter value: " value
result=$(factorial $value)
echo "The factorial of $value is: $result"
[root@qfedu.com ~]# bash test6.sh
Enter value: 5
The factorial of 5 is: 120
```
**扩展**
**内建命令**
因为安装了shell而产生的命令
# 作业01
要求最小化安装干净的系统,用脚本实现如下操作
```bash
先判断yum源是否可用
判断有没有epel yum源如果没有则安装epel yum源
判断epel yum源是否可用如果可用则安装sl
判断sl是否可用打印提示字符串 软件已经安装成功
安装httpd,安装完成后启动服务,判断服务是否可用
#vim /bin/bash
#判断yum是否可用
rpm -e lftp --nodeps
yum install lftp -y
rpm -q lftp
retval=$?
if [ $retval -ne 0 ];then
echo yum有问题 && exit 2
else
echo yum可用请继续
fi
#判断epel是否可用安装sl工具
yum install sl -y
retval=$?
if [ $retval -eq 0 ];then
echo EPEL源可用且sl工具已安装
else
echo EPEL不可用将要安装epel请稍后...
yum install epel-release -y
yum install sl -y
fi
sl
#安装并测试httpd服务
yum install -y httpd
systemctl start httpd
curl localhost
[ $? -eq 0 ] && echo 'Httpd服务已安装且可用恭喜你'
```
```
1.在上面脚本基础上添加脚本参数功能,用户可输入-v参数参数的功能为显示详细测试过程
```
```
2.请试着写出一个杀死进程httpd的shell脚本
```
```
3.请利用shell开发一个rsync服务的启动停止脚本
请利用shell开发一个rsync服务的管理脚本
a.sh -
```
服务的启动管理脚本
服务编译安装的nginx 二进制安装的tomcat 编译安装的redis 编译安装的rsync
过时技术 centos7之前使用的initd管理服务
centos7之后包括7官方用systemd替换initd
systemd 的服务管理方式
```
nginx 开机启动
systemctl enable nginx
nginx 启动
systemctl start nginx
```
initd的服务管理方式
```
nginx 开机启动
chkconfig --level 5 nginx on
nginx 启动
service nginx start
/etc/init.d/nginx start
自己编写的启动脚本默认不在chkconfig的管理之下
chkconfig --add nginx
```
# 常见环境变量
```bash
PATH变量
存储命令路径
# echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/root/bin
PS1
存储提示符格式
PS2
存储2级提示符格式
SHELLS //本系统支持的shell
PWD //当前工作目录
HOME //当前账户家目录
USER //当前登录账户
ID //当前账户ID
LANG=zh_CN.UTF-8 //字符集
HISTSIZE //历史命令条数
HOSTNAME //当前主机名称
```
# 作业02
用shell打印如下图形
```bash
********
********
********
********
********
*
**
***
****
*****
******
*
***
*****
*******
要求以上图形在用户执行脚本时可以让用户指定行数和列数
*
***
*****
*******
***
*****
*******
***
***
***
====生死分割线======
*
* *
* *
*******
用shell编写编译安装的nginx启动管理脚本
```
# seq命令
打印连续的数字
```bash
# seq 10
# seq 2 10
# seq 2 3 10
# seq 10 -1 2
# seq 10 -3 2
```
# 作业03
1. 编写shell脚本为不同分数的同学评级
60分以下 不及格
60-70 合格
70-90 良好
其他 优秀
2. 使用case语句编写脚本service.sh ,当给脚本传入不同参数的时候,执行不同的操作
service.sh start
服务启动成功
service.sh stop
服务关闭成功
service.sh restart
服务重启
service.sh restt
语法错误
3.昨天ftp的作业添加功能判断文件是否下载成功并给出提示