shell快讲第五节--shell语法基础

shell快讲第一节--shell基础
shell快讲第二节--管道与重定向
shell快讲第三节--正则表达式
shell快讲第四节--sed与awk
shell快讲第五节--shell语法基础
shell快讲第六节--shell函数编程
shell快讲第七节--shell编程规范与调试
shell快讲第八节--shell编程实战

编程语法基础

编程简述

从这节课开始我们就讲编程知识了,编程语言分为编译语言和脚本语言,大家知道的c/c++属于编译语言,shell属于脚本语言。代码编写也分为过程式、函数式、面向对象编程等,本书中shell的编写方式为过程式和函数式。下面回答几个问题:

1.什么是架构?

架构是指设计一个软件或者平台的相关技术组合,我们经常了解的是B/S、C/S架构就是一种简单的浏览器/服务端和客户端/服务端的架构,当然大型软件实际上架构往往很复杂。

2.什么是框架?

一门语言学完它的语法和编程知识其实距离能开发出软件距离还是很远的,因为主流的软件都是在框架下来开发的,比如图形化软件有图形化框架,web开发也有web相应框架,这些都是要学的,shell相对的比较好,基本使用不需要依赖任何框架,直接就是系统命令组合。

3.什么是过程式、函数式、面向对象编程?

过程式编程是指代码一行一行的向下执行,shell小脚本多为这样编程的,比如这节的代码都是过程式的。当然shell可以通过Function关键字实现函数式编程。但是shell做不到面向对象编程。

变量

变量我们可以理解为数学中的变量的概念,上过初中应该都能理解,任何语言都有变量,shell的变量想必大家也经常接触环境变量,没错变量分为很多种,环境变量,全局变量,局部变量等等说法,按照语言分,shell还是弱类型的变量,看到这里相比可能有点懵。那暂时知道如下几点就够了:

  • shell中变量是弱类型的语言,所有变量都是字符串,数字还是可以进行加减法操作
  • 变量名只能由英文字母,数字和下划线组成,而且首个字符不能是数字,也不可以是关键字
  • 变量使用$符号来调用
>>> a=123 #注意等号两边不能有空格
>>> echo $a #通过$变量名来使用变量
>>> echo ${a} #还可以使用${变量名}
>>> unset a #删除变量a
### 变量赋值

如上演示了一种赋值和调用的方式,实际上shell有多重赋值方式,这些赋值方式在脚本编程中都会用到的,我们现在来感受下:

>>> a=abc #如果是连贯的字面或者数字直接写
>>> a= 'a b c '#如果是不连贯的需要用引号,最好用单引号,shell单双引号有别
>>> read a #这里面a是变量名
>>> echo $a #检查变量的输入
>>> a=`ls` # `符号在shell里面代表可执行命令,执行命令的结果可以直接被赋值
>>> echo $a # 查看被赋值的命令
>>> echo 'echo $1' >test.sh #这是另外一种,这里先知道就好,这涉及到脚本的值传递
>>> bash ./test.sh nihao #检查nianhao是不是被传递进去了

问题:$a 什么时候可以作为字符串输出,什么时候可以作为变量输出?如下代码请亲自敲一下

>>> a=123 
>>> b="$a"
>>> c='$a'
>>> echo $b
>>> echo $c

数组

​ shell中的数组和数学概念上的数组是一样,shell只支持一维数组(回忆下你的初中数学课),但是shell的数组初始化非常的简单,数组的元素的下标从0开始。数组是一种数据类型,在编程过程中,我们会经常使用到它。

  1. 数组定义
>>> array=(1 2 3 4) #用空格分隔
>>> array1=(a bc d) #字母
  1. 获取单个元素,获取所有元素
>>> echo ${array[0]} #获取单个
>>> echo ${array[@]} #获取所有,有两种方法
>>> echo ${array[*]} 
  1. 获取数组长度
>>> echo ${#array[@]}
>>> echo ${#array[*]}

条件控制

if

if语句,作为条件控制语句我们是经常会用到的,比如“在满足特定条件下才能做什么事情”这种逻辑在写代码的时候我们会经常遇到。if语句的结构如下:

if command; then #这里的command返回值为0则触发条件,为其他值则不触发
    commands #这里command为if触发后才能执行
fi
-------------------------
if command; then #这里的command返回值为0则触发条件,为其他值则不触发
    commands #这里command为if触发后才能执行
else
    commands #如果条件不为0执行这个commands
fi

各种if的结构,如下这种都可以的,大家要明白其中的原理,不要死记。

if [ "$a" -eq "123" ] #注意:中括号与表达式必须间隔空格
then
    echo '$a等于123'
fi
--------------------------
if [ "$a" -eq "123" ];then echo '$a等于123';fi # 还可以写成一行
---------------------------
if pwd #或者如下这种样子
then
    echo "It worked"
fi
----------------------------
if [ "$a" -eq "123" ] 
then
    echo '$a等于123'
else
    echo '$a不等于123'
fi

我们来看一个比较实际的例子,执行一个命令,然后判断命令是否执行成功,如果自行编写无法运行,可见代码例子

#!/bin/bash
#1-06-01.sh
#date:2019.03.10

systemctl restart sshd #这里大家根据实际情况随便执行一个服务,
if [ $? -ne 0 ];then
    echo -e "\033[31m\033[01m 启动服务失败 \033[0m"
else
    echo "启动sshd成功"
fi

当然if语句是支持嵌套和和更为复杂的if ...else...的复杂模式if...elif... 我先给大家一个例子,大家消化一下。如果理解不了也没关系,用的多了自然就明白了。大家尝试编写下如下代码代码例子2

#!/bin/bash
#1-06-02.sh
if [[ $1 = 'tomcat' ]];
then
  echo "Input is tomcat"
elif [[ $1 = 'redis' ]] || [[ $1 = 'zookeeper' ]];
then
  echo "Input is $1"
else
  echo "Input Is Error."
fi

>>> ./1-06-02.sh zookeeper
>>> ./1-06-02.sh tomcat
>>> ./1-06-02.sh mysql 

在给大家看个If嵌套语句,这个比较好理解,实际使用中尽量别写这种逻辑复杂的情况,除非无法避免,下面的脚本需要sudo权限才能查看,因为passwd文件权限要求高,请某个同学尝试解释下代码的意思:

#!/bin/bash
#
testuser=fonsview
#
if grep $testuser /etc/passwd
then
    echo "The user $testuser exists on this system."
else
    echo "The user $testuser does not exist on this system."
if ls -d /home/$testuser/
then
    echo "However, $testuser has a directory."
fi #思考这个fi是谁的
fi #思考这个fi是谁的

下面介绍If当中最复杂的地方了,也是需要死记硬背的地方,大家如果记不住可以先了解,日后百度即可,参考文献

内容 描述
if [ -f file ] 如果文件存在 -eq 等于,如:if [ "b" ]
if [ -d directory ] 如果目录存在 -ne 不等于,如:if [ "b" ]
if [ -r/w/x/s file ] 如果文件存在且可读/写/执行/非空 -gt 大于,如:if [ "b" ]
if [ "$string" != "string2" ]字符串1(变量)不等于字符串2 -ge 大于等于,如:if [ "b" ]
if [ "$string" =="string2" ] 字符串1(变量)等于字符串2 -lt 小于,如:if [ "b" ]
if [ -n $string ] 如果string 非空(非0),返回0(true) -le 小于等于,如:if [ "b" ]
if [ -z $string ] 如果string 为空 ,返回0 < 小于(需要双括号),如:(("b"))
if [ ! 表达式 ] 逻辑非 <= 小于等于(需要双括号),如:(("b"))
>= 大于等于(需要双括号),如:(("b")) > 大于(需要双括号),如:(("b"))

case

case语句,什么时候用到?当你需要不停的if... if... if... 的时候... ,case的语法块结构也没什么新意,case...esac,

case用法也有局限性,不过一般使用是够的的,下面体验下代码例子3


#!/bin/sh
#1-06-03.sh
case $1 in
        start | begin)
          echo "start something"
        ;;
        stop | end)
          echo "stop something"
        ;;
        *) #星号匹配通配任意字符串
          echo "Ignorant"
        ;;
esac
>>> ./test.sh start 
>>> ./test.sh stop

看个实际的例子大家感受下,大家自己敲击一下

#!/bin/bash
read -p "press some key ,then press return :" KEY
case $KEY in
    [a-z]|[A-Z])
    echo "It's a letter."
    ;;
    [0-9]) 
    echo "It's a digit."
    ;;
    *) #星号匹配通配任意字符串
    echo "It's function keys、Spacebar or other ksys."
    ;;
esac

循环

for

重复执行一系列命令在编程中很常见。通常你需要重复一组命令直至达到某个特定条件,比如处理某个目录下的所有文件、系统上的所有用户或是某个文本文件中的所有行。bash shell提供了 for 命令,允许你创建一个遍历一系列值的循环。每次迭代都使用其中一个值来执行已定义好的一组命令。下面是bash shell中 for 命令的基本格式

for var in list
do
    commands
done

下面列一下常见的几种for用法模式

------ 类似C语言for循环-----
for ((i=0;i<10;i++))#双括号用于扩展逻辑关系
do
    echo $i
done
----第二种for 数组应发------
array=(1 2 3 4)
for item in ${array[@]}
do
    echo $item
done
-----for 对执行命令结果进行遍历-------
for i in `ls`
do
    echo $i
done

当然for也有不少“孔乙己”式的用法,我甚至觉得这就是为啥总有人想把shell换掉(瞎说的),下面列一些大家也经常遇到的For用法,这几个用法功能一样

for ((i=1; i<=100; i ++))
do
    echo $i
done

-------------------------------
for i in {1..100}
do
    echo $i
done
-----------------------
for i in `seq 1 100`
do
    echo $i
done

下面的脚本需要大家自己动手敲一遍并能正确执行,同时思考下for在实际生产场景如何使用

#!/bin/bash

for file in /home/rich/test/*
do
    if [ -d "$file" ]
    then
        echo "$file is a directory"
    elif [ -f "$file" ]
    then
        echo "$file is a file"
    fi
done

while

while 命令某种意义上是 if-then 语句和 for 循环的混杂体。 while 命令允许定义一个要测试的命令,然后循环执行一组命令,只要定义的测试命令返回的是退出状态码 0,while有一个反命令,是until 用法和while一样,但是它是退出状态码不为0的时候执行

num=10
while [ $num -gt 0 ]
do
    echo $num
    ((num--))#双括号用于数学运算,或者使用expr,记住最常用的
done
-------------------
a=0
until [ $a -gt 10 ] #a大于10不成立,所以执行
do
   echo $a
   a=`expr $a + 1`
done

循环经常用于死循环的场景,比如我写一个死循环,每隔30秒不停的探测某个web服务是否在开启,或者写个密码登录器,只有到输入正确的密码才会登录进去等等,那么这种场景就需要想办法跳出循环,下面我们看如何跳出循环

break

break命令允许跳出所有循环(终止执行后面的所有循环)。下面代码大家敲一下感受下break的用法

#!/bin/bash
while :
do
    echo -n "输入 1 到 5 之间的数字:"
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你输入的数字为 $aNum!"
        ;;
        *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
            break
        ;;
    esac
done

continue

continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

#!/bin/bash
while :
do
    echo -n "输入 1 到 5 之间的数字: "
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你输入的数字为 $aNum!"
        ;;
        *) echo "你输入的数字不是 1 到 5 之间的!"
            continue
            echo "游戏结束"
        ;;
    esac
done

大家执行下看看和上面的break有何不同 ,没错“游戏结束”这句话永远也不会执行,break和continue除了使用在while当中,还可以使用在for循环当中,使用的方法都是一样,在你认为可以结束当前或者整个循环的地方加上它就可以了

你可能感兴趣的:(shell快讲第五节--shell语法基础)