【图文教程】Shell编程

Shell编程

  • 1. shell脚本介绍
  • 2. shell脚本结构和执行
  • 3. date命令用法
  • 4. shell脚本中的变量
  • 5. shell脚本中的逻辑判断
  • 6. 文件目录属性判断
  • 7. if特殊用法
  • 8. case判断
  • 9. for循环
  • 10. while循环
  • 11. break跳出循环
  • 12. continue结束本次循环
  • 13. exit退出整个脚本
  • 14. select循环
  • 15. shell中的函数
  • 16. shell中的数组
  • 17. 扩展

1. shell脚本介绍

讲义

1. shell是一种脚本语言 和传统的开发语言比较,会比较简单
2. shell有自己的语法;可以使用逻辑判断、循环等语法
3. 可以自定义函数,目的就是为了减少重复的代码
4. shell是系统命令的集合
5. shell脚本可以实现自动化运维,能大大增加我们的运维效率

2. shell脚本结构和执行

  • shell脚本格式
1. 开头需要加 #!/bin/bash
2. 以 # 开头的行作为解释说明
3. 脚本的名字以 .sh 结尾,用于区分这是一个 shell 脚本
  • 编辑01.sh示例
[root@test01 shell]# vi 01.sh

#!/bin/bash      #固定开头格式
#written by sc   #固定开头格式,意思是谁写的
#2019-06-17      #固定开头格式,意思是年月日
echo "123"       #打印 123
w                #查看负载
ls               #查看当前目录
  • 执行01.sh示例
[root@test01 shell]# sh 01.sh 
123
 19:46:25 up  2:41,  2 users,  load average: 0.05, 0.03, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.85.1     16:47    2:16m  0.07s  0.01s vi 01.sh
root     pts/1    192.168.85.1     19:43    1.00s  0.11s  0.00s sh 01.sh
01.sh
  • 执行脚本有两种方法
方法一:

/bin/sh实际是bash的软连接;其实是真正执行的是bash

[root@test01 shell]# ls -l /bin/bash
-rwxr-xr-x. 1 root root 964608 Oct 31  2018 /bin/bash
[root@test01 shell]# ls -l /bin/sh
lrwxrwxrwx. 1 root root 4 Mar 19 07:53 /bin/sh -> bash
[root@test01 shell]# bash 01.sh 
123
 09:46:46 up 39 min,  1 user,  load average: 0.30, 0.16, 0.10
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.85.1     09:33    6.00s  0.10s  0.00s w
01.sh


方法二:

[root@test01 shell]# chmod a+x 01.sh    #增加执行权限
[root@test01 shell]# ./01.sh            #可执行脚本        
123
 22:03:55 up  4:59,  1 user,  load average: 0.02, 0.04, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/1    192.168.85.1     19:43    3.00s  0.09s  0.00s /bin/bash ./01.sh
01.sh
  • 查看脚本执行过程:bash -x 脚本名称
[root@test01 shell]# sh -x 01.sh 
 + echo 123
123
 + w
 09:40:43 up 33 min,  1 user,  load average: 0.00, 0.02, 0.06
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.85.1     09:33    3.00s  0.08s  0.01s w
 + ls
01.sh
  • 查看脚本是否语法错误: bash -n 脚本名称
[root@test01 shell]# vim 01.sh 

#!/bin/bash
echo "123  #注意:为了测试 bash -n 把123右侧的双引号去掉
w
ls

[root@test01 shell]# sh -n 01.sh  #执行脚本
01.sh: line 2: unexpected EOF while looking for matching `"'  #检查完以后显示语法是错的
01.sh: line 5: syntax error: unexpected end of file

3. date命令用法

  • 时间格式用法
时间格式举例:

[root@test01 shell]# date +%Y  #大写Y 年份2019
2019
[root@test01 shell]# date +%y  #小写y 简写的年 年份19
19
[root@test01 shell]# date +%m  #小写m 月份06
06
[root@test01 shell]# date +%M  #分钟22
22
[root@test01 shell]# date +%d  #日期16
16
[root@test01 shell]# date +%D  #年月日20190616
06/16/19
[root@test01 shell]# date +%F  #日期格式2019-06-16
2019-06-16
[root@test01 shell]# date +%H  #大写H 小时11
11
[root@test01 shell]# date +%h  #小写h 英文的月
Jul
[root@test01 shell]# date +%S  #大写S54
54
[root@test01 shell]# date +%T=date +%H:%M:%S  #常规时间11:42:40
11:42:40 
[root@test01 shell]# date +%w  #星期几0
0
[root@test01 shell]# date +%W  #今天是今年的第2323


日历:

[root@test01 shell]# cal  #显示当月日历
      June 2019     
Su Mo Tu We Th Fr Sa
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30

[root@test01 TD]# cal 11 2019  #显示指定月年
    November 2019   
Su Mo Tu We Th Fr Sa
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30


时间戳举例:

[root@test01 shell]# date +%s  #小写s 时间戳1560656445
1560656445 
[root@test01 shell]# date -d @1560656445
Sun Jun 16 11:40:45 CST 2019
[root@test01 shell]# date +%s -d "2019-06-16 11:40:45"
1560656445
  • date -d选项用法
-1+1 年月日举例:

[root@test01 shell]# date -d "-1 day" +%F    #一天前
2019-06-15
[root@test01 shell]# date -d "+1 day" +%F    #一天后
2019-06-17
[root@test01 shell]# date -d "-1 week" +%F   #一周前
2019-11-11
[root@test01 shell]# date -d "+1 week" +%F   #一周后
2019-11-25
[root@test01 shell]# date -d "-1 month" +%F  #一月前
2019-05-16
[root@test01 shell]# date -d "+1 month" +%F  #一月后
2019-07-16
[root@test01 shell]# date -d "-1 year" +%F   #一年前
2018-06-16
[root@test01 shell]# date -d "+1 year" +%F   #一年后
2020-06-16


-1+1 小时分钟举例:

[root@test01 shell]# date -d "-1 hour" +%T   #一小时前
11:06:03
[root@test01 shell]# date -d "+1 hour" +%T   #一小时后
13:06:13
[root@test01 shell]# date -d "-1 min" +%T    #一分钟前
12:06:26
[root@test01 shell]# date -d "+1 min" +%T    #一分钟后
12:08:33

4. shell脚本中的变量

讲义

1. 当脚本中使用某个字符串较频繁并且字符串长度很长时就应该使用变量代替(比如a=jdjjdjdddx)
2. 使用条件语句时,常使用变量 if [ $a -gt 1 ]; then ... ; fi
3. 引用某个命令的结果时,用变量替代 n=wc -l 1.txt
4. 写和用户交互的脚本时,变量也是必不可少的 read -p "Input a number: " n; echo $n 如果没写这个n,可以直接使用$REPLY
5. 内置变量 $0, $1, $2… $0表示脚本本身,$1 第一个参数,$2 第二个 .... $#表示参数个数
6. 数学运算a=1;b=2; c=$(($a+$b))或者$[$a+$b]

5. shell脚本中的逻辑判断

讲义

1. 格式1if 条件 ; then 语句; fi
2. 格式2if 条件; then 语句; else 语句; fi
3. 格式3if; then … ;elif …; then …; else; fi
4. 逻辑判断表达式:if [ $a -gt $b ]; if [ $a -lt 5 ]; if [ $b -eq 10 ]-gt (>); -lt(<); -ge(>=); -le(<=);-eq(==); -ne(!=) 注意到处都是空格
5. 可以使用 && || 结合多个条件
6. if [ $a -gt 5 ] && [ $a -lt 10 ]; then
7. if [ $b -gt 5 ] || [ $b -lt 3 ]; then
  • 格式1:if 条件 ; then 语句; fi
#!/bin/bash      #开头固定格式
a=5              #变量 a=5
if [ $a -gt 3 ]  #if是判断条件,变量a大于3的时候
then             #固定格式
   echo ok       #输出ok
fi               #固定格式
  • 格式2:if 条件; then 语句; else 语句; fi
#!/bin/bash      #开头固定格式
a=1              #变量 a=1
if [ $a -gt 3 ]  #if是判断条件,变量a大于3的时候
then             #固定格式
   echo ok       #输出ok
else             #else表示除if以外,剩下的情况
   echo nook     #输出nook
fi               #固定格式
  • 格式3:if …; then … ;elif …; then …; else …; fi
#!/bin/bash                              #开头固定格式
read -p "Please enter your test sco:" a  #输入的数字赋值到了a
if [ $a -lt 60 ]                         #if是判断条件,赋值小于60
then                                     #固定格式
   echo "Too bad the"                    #打印 Too bad the
elif [ $a -gt 60 ] && [ $a -lt 85 ]      #elif除if判断条件以外,另外的判断条件,赋值大于60并且小于85
then                                     #固定格式
   echo "Ok!"                            #打印 ok
else                                     #else表示除上面if和elif判断以外,剩下的情况
   echo "Good!"                          #打印 good
fi                                       #固定格式


[root@test01 shell]# sh if03.sh 
Please enter your test sco:45
Too bad the
[root@test01 shell]# sh if03.sh 
Please enter your test sco:66
Ok!
[root@test01 shell]# sh if03.sh 
Please enter your test sco:99
Good!
  • 逻辑判断符号:
符号 含义
-gt 大于
-lt 小于
-eq 等于
-ne 不等于
-ge 大于等于
-le 小于等于
  • 可以使用 &&(并且) ||(或者) 结合多个条件
if [ $a -gt 5 ] && [ $a -lt 10 ]; then
if [ $b -gt 5 ] || [ $b -lt 3 ]; then

6. 文件目录属性判断

讲义

[ -f file ]判断是否是普通文件,且存在
[ -d file ] 判断是否是目录,且存在
[ -e file ] 判断文件或目录是否存在
[ -r file ] 判断文件是否可读
[ -w file ] 判断文件是否可写
[ -x file ] 判断文件是否可执行
  • 判断是否是普通文件,且存在: [ -f file ]
#!/bin/bash           #开头固定格式
f="/tmp/sclinux"      #变量
if [ -f $f ]          #判断/tmp/sclinux是否是普通文件,且存在
then                  #固定格式
   echo $f exist      #打印/tmp/sclinux存在
else                  #else表示除if以外,剩下的情况
   touch $f           #创建/tmp/sclinux
fi                    #固定格式


[root@test01 shell]# sh -x file01.sh   #执行脚本
+ f=/tmp/sclinux
+ '[' -f /tmp/sclinux ']'
+ touch /tmp/sclinux                   #如果/tmp/sclinux这个文件不存在,创建       


[root@test01 shell]# sh -x file01.sh   #再次执行脚本
+ f=/tmp/sclinux
+ '[' -f /tmp/sclinux ']'
+ echo /tmp/sclinux exist
/tmp/sclinux exist                     #/tmp/sclinux已经显示存在
  • 判断是否是目录,且存在: [ -d file ]
#!/bin/bash           #开头固定格式
f="/tmp/sclinux"      #变量
if [ -d $f ]          #判断/tmp/sclinux是否是目录,且存在
then                  #固定格式
   echo $f exist      #打印/tmp/sclinux存在
else                  #else表示除if以外,剩下的情况
   touch $f           #创建/tmp/sclinux
fi                    #固定格式


[root@test01 shell]# sh -x file02.sh  #执行脚本
+ f=/tmp/sclinux
+ '[' -d /tmp/sclinux ']'
+ touch /tmp/sclinux                  
#虽然文件和目录都存在,但是可以重复touch的,摸一下的意思,改变的是atime,mtime,ctime
  • 判断文件或目录是否存在: [ -e file ]
#!/bin/bash           #开头固定格式
f="/tmp/sclinux"      #变量
if [ -e $f ]          #判断/tmp/sclinux判断文件或目录是否存在
then                  #固定格式
   echo $f exist      #打印/tmp/sclinux存在
else                  #else表示除if以外,剩下的情况
   touch $f           #创建/tmp/sclinux
fi                    #固定格式


root@test01 shell]# sh -x file03.sh 
+ f=/tmp/sclinux
+ '[' -e /tmp/sclinux ']'
+ echo /tmp/sclinux exist
/tmp/sclinux exist
  • 判断文件是否可读: [ -r file ]
#!/bin/bash
f="/tmp/sclinux"
if [ -r $f ]
then
   echo $f readable
fi


[root@test01 shell]# sh file03.sh 
/tmp/sclinux readable
  • 判断文件是否可写: [ -w file ]
#!/bin/bash
f="/tmp/sclinux"
if [ -w $f ]
then
   echo $f writeable
fi


[root@test01 shell]# sh file03.sh 
/tmp/sclinux writeable
  • 判断文件是否可执行: [ -x file ]
#!/bin/bash
f="/tmp/sclinux"
if [ -x $f ]
then
   echo $f exeable
fi


[root@test01 shell]# sh file03.sh  #因为不可执行,所以没有任何的输出
  • 并且 &&
f="/root/ceshi"
[ -f $f ] && rm -f $f  #前一条命令执行成功才会继续执行之后的命令

等同于下面的表达方式

if [ -f $f ]
then
rm -rf $f
fi
  • 或者 ||
f="/root/ceshi"
[ -f $f ] || touch $f  #前面命令不成功时,执行后面的命令

等同于下面的表达方式

if [ ! -f $f ]  # “!” 取反的意思,表示了如果这条命令不成功,就往下执行
then
touch $f
fi

7. if特殊用法

讲义

if特殊用法

1. if [ -z "$a" ] 逻辑条件是:变量a的值为空
2. if [ -n "$a" ] 逻辑条件是:变量a的值不为空
3. if grep -wq '123' 1.txt; then 逻辑条件是:1.txt中含有'123'的行
4. if [ ! -e file ]; then 逻辑条件是:文件不存在

圆括号与方括号的区别:

1. if (($a<1)); then … 等同于 if [ $a -lt 1 ]; then…
2. [ ] 中不能使用<,>,==,!=,>=,<=这样的符号
  • 常见的一些用法注意
1. if -z或者if -n 都不能作用在文件上,只能作用在变量上。
2. if [ -z "$a" ] 这个表示当变量a的值为空时会怎么样
3. !-z=-n
4. !-n=-z
  • if [ -z “$a” ] 逻辑条件是:变量a的值为空
#!/bin/bash
n=`wc -l /etc/passwd |awk '{print $1}'`   #变量/etc/passwd的行数截取第一段
if [ -z "$n" ]                            #条件:是否为空
then                                      #固定格式
   echo error                             #如果为空打印错误
   exit                                   #如果为空退出
elif [ $n -gt 20 ]                        #如果变量n的赋值于20
then                                      #固定格式
   echo ok                                #打印ok
fi                                        #固定格式


[root@test01 shell]# sh -x if04.sh 
++ awk '{print $1}'
++ wc -l /etc/passwd
+ n=35
+ '[' -z 35 ']'
+ '[' 35 -gt 20 ']'
+ echo ok
ok
  • if [ -n “$a” ] 表示当变量a的值不为空,或者说这个文件内容不为空
-n 判断变量的时候,需要用""双引号引起来,若是文件的时候,则不需要用双引号引起来

[root@test01 shell]# if [ -n file3.sh ]; then echo ok; fi
ok
[root@test01 shell]# if [ -n "$b" ]; then echo $b; else echo "b is null"; fi
b is null

8. case判断

讲义

case格式:

case 变量名 in
value1)
command
;;
value2)
command
;;
*)
commond
;;
esac


如果case中的某个value是一样的,我们可以这样写:

在case程序中,可以在条件中使用 |,表示或的意思,
比如

2|3)
command
;;
  • case脚本案例
#输入非数字,或者大于100,并且输入任意数字可以显示出来

#!/bin/bash
read -p "Please input a number: " n   #请输入数字
if [ -z "$n" ]                        #如果为空
then
    echo "Please input a number."     #请输入数
    exit 1                            #退出并返回一个值
fi

n1=`echo $n|sed 's/[0-9]//g'`         #打印出的数字,过滤其中只要包含0-9就为空
if [ -n "$n1" ]                       #如果这个变量不为空
then
 echo "Please input a number."        #请继续输入数字
 exit 1                               #退出并返回一个值
fi

if [ $n -ge 0 ] && [ $n -lt 60 ]      #>=0并且<60
then
    tag=1                             #标签1
elif [ $n -ge 60 ] && [ $n -lt 85 ]   #>=60并且<85
then
    tag=2                             #标签2
elif [ $n -ge 85 ]  && [ $n -lt 100 ] #>=85并且<100
then
    tag=3                             #标签3
else [ $n -ge 100 ]                   #>=100
    tag=4                             #标签4
fi

case $tag in
    1)
        echo "not ok"                 #标签1显示 "not ok"
        ;;
    2)
        echo "ok"                     #标签2显示 "ok"
        ;;
    3)
        echo "That's great"           #标签3显示 That's great"
        ;;
    4)
        echo "Very good"              #标签4显示 "Very good"
        ;;
esac

9. for循环

重复执行一系列命令在 编程中很常见。通常你需要重复一组命令直到达到某个特定条件,比如处理某个目录下的所有文件、系统上的所有用户或者是某个文本文件中的所有行。
常见的两种循环,在脚本中普遍被用到。
for循环
while循环

  • for循环演示1:累加求和
#!/bin/bash
sum=0
for i in `seq 1 100`  #打印1-100的数字,i是变量
do
   sum=$[$sum+$i]     #求和的固定格式
done
   echo $sum          #打印sum值
  • for循环演示2:遍历一个目录的目录或者文件
#查看/root/shell/下的所有文件

#!/bin/bash
cd /root/shell/             
for i in ls /root/shell/    
do
   if [ -d $i ]             
      then
      ls $i
  fi
done


[root@sc01 shell]# sh -x 3.sh
+ cd /root/shell/
+ for i in ls /root/shell/
+ '[' -d ls ']'
+ for i in ls /root/shell/
+ '[' -d /root/shell/ ']'
+ ls /root/shell/
1.sh  2.sh  3.sh  test.sh

10. while循环

  • while循环演示1

每隔30秒检查一下系统负载,当系统的负载大于10的时候,发一封邮件(监控脚本) 最小单元是任务计划 cron

#!/bin/bash
while :
#冒号:表示死循环的意思,或者1,或者 true都是死循环
do
load=`w|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1`
#代码名词释义
#w         #查看系统负载
#uptime    #可以直接显示 w 系统负载的第一行,就可以省去 head -1
#head -1   #取第一行
#awk -F 'load average: ' '{print $2}'  #以'load average: '分隔,输出第二段
#cut -d . -f1  #以 . 分隔 取第一段
if [ $load -gt 10 ]
then
/usr/local/sbin/mail.py test_emali_0711@163.com"load high" "$load"
fi
sleep 30  #休眠30秒,因为检查系统负载,不需要一直去检查,过一会再看
done
  • while循环演示2
#!/bin/bash
while :
do
   read -p "Please input a number: " n  #请输入数字
   if [ -z "$n" ]                       #如果输入的为空
   then
       echo "请输入数字"                  #请输入数字
       continue                         #重复循环
   fi
   n1=`echo $n|sed 's/[0-9]//g'`        #变量,打印的数字,过滤其中0-9数字为空
   if [ -n "$n1" ]                      #如果不为空
   then
       echo "请输入纯数字"                #请输入纯数字
       continue                         #重复循环
   fi
   break                                #跳出循环
done
echo $n                                 #打印 $n 的结果

11. break跳出循环

  • break 常用于循环语句中,跳出整个循环语句,直接结束所有循环
#!/bin/bash
for i in `seq 1 5`
do
    echo $i
    if [ $i -eq 3 ]
    then
        break
    fi
    echo $i
done
    echo aaaaaa


[root@test01 shell]# sh -x break.sh 
++ seq 1 5
+ for i in '`seq 1 5`'
+ echo 1
1
+ '[' 1 -eq 3 ']'
+ echo 1
1
+ for i in '`seq 1 5`'
+ echo 2
2
+ '[' 2 -eq 3 ']'
+ echo 2
2
+ for i in '`seq 1 5`'
+ echo 3
3
+ '[' 3 -eq 3 ']'
+ break
+ echo aaaaaa
aaaaaa


[root@test01 shell]# sh break.sh 
1
1
2
2
3
aaaaaa

12. continue结束本次循环

  • 忽略continue之前的代码,直接进行下一次循环
#!/bin/bash
for i in `seq 1 5`
do
  echo $i
  if [ $i -eq 3 ]
  then
    continue
  fi
  echo $i
 done
  echo aaaaaa


[root@test01 shell]# sh continue.sh 
1
1
2
2
3
4
4
5
5
aaaaaa

13. exit退出整个脚本

  • exit可以定义退出的数值,可以用于确定脚本运行到什么地方的时候结束
#!/bin/bash
for i in `seq 1 5`
do
  echo $i
  if [ $i -eq 3 ]
  then
      exit
  fi
  echo $i
done
echo $i


[root@test01 shell]# sh exit 
1
1
2
2
3

14. select循环

  • select循环演示

select也是循环的一种,它比较适合用在用户选择的情况下

比如,我们有一个这样的需求,运行脚本后,让用户去选择数字,选择1,会运行w命令,选择2运行top命令,选择3运行free命令,选择4退出。脚本这样实现

#!/bin/bash
echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
echo
select command in w top free quit
do
    case $command in
    w)
        w
        ;;
    top)
        top
        ;;
    free)
        free
        ;;
    quit)
        exit
        ;;
    *)
        echo "Please input a number:(1-4)."
        ;;
    esac
done


[root@test01 shell]# sh select.sh 
Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit

1) w
2) top
3) free
4) quit
#? 1
 13:17:03 up 19:00,  1 user,  load average: 0.07, 0.06, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.85.1     08:33    7.00s  0.22s  0.21s -bash
#? 3
              total        used        free      shared  buff/cache   available
Mem:        1005628      691060       66148        8200      248420      110332
Swap:       2097148         264     2096884
#? 4
[root@test01 shell]#

我们发现,select会默认把序号对应的命令列出来,每次输入一个数字,则会执行相应的命令,命令执行完后并不会退出脚本。它还会继续让我们再次输如序号。序号前面的提示符,我们也是可以修改的,利用变量PS3即可,再次修改脚本如下

#!/bin/bash
PS3="Please select a number: "
echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
echo
select command in w top free quit
do
    case $command in
    w)
        w
        ;;
    top)
        top
        ;;
    free)
        free
        ;;
    quit)
        exit
        ;;
    *)
        echo "Please input a number:(1-4)."
        ;;
    esac
done


[root@test01 shell]# sh select.sh 
Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit

1) w
2) top
3) free
4) quit
Please select a number: 1
 13:19:38 up 19:03,  1 user,  load average: 0.14, 0.09, 0.06
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.85.1     08:33    2.00s  0.21s  0.21s -bash
Please select a number: 3
              total        used        free      shared  buff/cache   available
Mem:        1005628      691056       66000        8200      248572      110324
Swap:       2097148         264     2096884
Please select a number: 4
[root@test01 shell]#

如果想要脚本每次输入一个序号后就自动退出,则需要再次更改脚本如下

#!/bin/bash
PS3="Please select a number: "
echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
echo
select command in w top free quit
do
    case $command in
    w)
        w;exit
        ;;
    top)
        top;exit
        ;;
    free)
        free;exit
        ;;
    quit)
        exit
        ;;
    *)
        echo "Please input a number:(1-4)."
        ;;
    esac
done


[root@test01 shell]# sh select.sh 
Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit

1) w
2) top
3) free
4) quit
Please select a number: 1
 13:24:09 up 19:07,  1 user,  load average: 0.00, 0.04, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.85.1     08:33    1.00s  0.22s  0.22s -bash
[root@test01 shell]#

15. shell中的函数

shell函数定义:shell函数相当于一个子shell,就是把一段代码整理到了一个小单元中,并给这个小单元起一个名字,当用到这段代码时直接调用这个小单元的名字即可。

  • shell函数格式模板及内建变量含义
function f_name() {
                      command
             }
用于定义加法的函数,shell中定义的函数,必须放在最前面
在shell里面需要优先定义函数,比如在调用这个函数的时候,函数还没有定义,就会报错
在想要调用哪一个函数,就必须在调用语句之前,先定义这个函数

注释:
function 后是函数的名字,并且 function 这个单词是可以省略掉的
花括号{} 里面为具体的命令

函数,可以直接写在脚本内,相当于直接调用

內建变量含义:

$1 第一个参数
$2 第二个参数
$3 第三个参数
...
~
$n 第n个参数
$# 总共有几个参数
$0 脚本名字
  • shell函数示例一:打印参数
#!/bin/bash                                   #开头固定格式
function input()                              #函数 自定义名称:input 
{                                             #固定格式
echo '$1'=$1 '$2'=$2 'S3'=$3 '$0'=$0 '$#'=$#  #内建变量参数
}                                             #固定格式
input a b c                                   #定义参数内容


[root@test01 shell]# sh function.sh 
$1=a $2=b S3=c $0=function.sh $#=3
[root@test01 shell]# sh -x function.sh 
+ input a b c
+ echo '$1=a' '$2=b' S3=c '$0=function.sh' '$#=3'
$1=a $2=b S3=c $0=function.sh $#=3
  • shell函数示例二:传递参数求和
#!/bin/bash         #开头固定格式
function sum()      #函数 自定义名称:sum
{                   #固定格式
s=$[$1+$2]          #内建变量参数
echo SUM=$s         #打印变量值
}                   #固定格式
sum 10 20           #定义参数内容


[root@test01 shell]# sh function01.sh 
SUM=30
  • shell函数示例三:输入网卡的名字,检查网卡的IP地址
[root@test01 shell]# ifconfig |grep -A1 "ens33: "  #在网卡里过滤 ens33: 当前行和下一行
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.85.130  netmask 255.255.255.0  broadcast 192.168.85.255
[root@test01 shell]# ifconfig |grep -A1 "ens33: " |awk '/inet/ {print $2}'  #过滤出含有 inet 行,第二段内容,分段符默认为空格
192.168.85.130


#!/bin/bash  #开头固定格式
ip()         #函数 自定义名称:ip
{            #固定格式
    ifconfig |grep -A1 "$1: " |awk '/inet/ {print $2}'  #网卡里过滤当前行和下一行参数,并且过滤 inet 行第二段内容
}            #固定格式

read -p "Please input the eth name: " eth  #输入的内容赋值到了eth
ip $eth                                    #ip定义变量


[root@test01 shell]# sh function02.sh 
Please input the eth name: ens37
192.168.85.130
[root@test01 shell]# sh function02.sh 
Please input the eth name: ens33:0
192.168.94.150
[root@test01 shell]# sh function02.sh 
Please input the eth name: ens37
192.168.159.130

16. shell中的数组

  • 定义数组,查看数组
[root@test01 shell]# b=(1 2 3 4)   #定义数组b,1 2 3 4为其元素
[root@test01 shell]# echo ${b[@]}  #方法一:查看数组元素
1 2 3 4
[root@test01 shell]# echo ${b[*]}  #方法二:查看数组元素
1 2 3 4
[root@test01 shell]# echo ${b[1]}  #查看数组元素b1,即第二位
2
[root@test01 shell]# echo ${b[4]}  #查看数组元素b4,为空,因为只有4位,b4即为第五位

[root@test01 shell]# echo ${b[0]}  #b[0]=1 为第一位
1
[root@test01 shell]# echo ${#b[@]} #查看数组元素总数 加#号
4
[root@test01 shell]# echo ${#b[*]}
4
  • 数组的元素的赋值
[root@test01 shell]# echo ${b[*]}
1 2 3 4
[root@test01 shell]# b[3]=qq      #把qq赋给b3,即第4[root@test01 shell]# echo ${b[*]}
1 2 3 qq
[root@test01 shell]# b[3]=100     #把100赋给b3,即第4[root@test01 shell]# echo ${b[*]}
1 2 3 100
[root@test01 shell]# b[5]=100     #把100赋给b5,因为b5不存在,则自动创建;注意b4不存在
[root@test01 shell]# echo ${b[*]}
1 2 3 100 100
[root@test01 shell]# b[4]=dd      #把dd赋给b4,即第5位;注意b5的区别
[root@test01 shell]# echo ${b[*]}
1 2 3 100 dd 100                  #第5位为dd,证明b4之前为空
  • 数组元素的删除
[root@test01 shell]# echo ${b[*]}
1 2 3 100 dd 100
[root@test01 shell]# unset b[5]    #删除b5元素,即第6[root@test01 shell]# echo ${b[*]}  #成功删除100
1 2 3 100 dd
[root@test01 shell]# unset b       #清空数组元素
[root@test01 shell]# echo ${b[*]}
  • 数组中元素的截取
[root@test01 shell]# a=(`seq 1 10`)       #定义数组a
[root@test01 shell]# echo ${a[*]}
1 2 3 4 5 6 7 8 9 10
[root@test01 shell]# echo ${a[*]:5:4}     #从第5位开,截取46 7 8 9
[root@test01 shell]# echo ${a[*]}
1 2 3 4 5 6 7 8 9 10
[root@test01 shell]# echo ${a[*]:0-4:3}   #从倒数第5位(0 1 2 3 4)开始,截取37 8 9
  • 数组中元素的替换
[root@test01 shell]# echo ${a[*]}
1 2 3 4 5 6 7 8 9 10
[root@test01 shell]# echo ${a[*]/2/11}    #把2替换为11
1 11 3 4 5 6 7 8 9 10
  • 直接赋值(需要用括号括起来)
[root@ying01 shell]# echo ${a[*]}
1 2 3 4 12 6 7 8 9 10
[root@ying01 shell]# c=(${a[*]/6/18})     #把更新的数组 赋予c数组
[root@ying01 shell]# echo ${c[*]}         #打印c数组
1 2 3 4 12 18 7 8 9 10

17. 扩展

select用法 http://www.apelearn.com/bbs/thread-7950-1-1.html
shell多线程 http://blog.lishiming.net/?p=448
给你提供一本电子书 链接:http://pan.baidu.com/s/1mg49Taw 密码:yk4b
shell习题做一下 http://www.apelearn.com/study_v2/chapter15.html#shll

你可能感兴趣的:(Linux,【图文教程】)