为了能到远方,脚下的每一步都不能少.|

2024-02-21-物联网系统编程(1-Shell语言)

1. Shell概述

shell作为应用程序,交互式地解释、执行用户输入的命令,将用户的操作翻译成机器可以识别的语言,完成相应功能。

1.1 shell 脚本用途

shell 描述
bsh 一种最早出现在Unix系统上的标准shell,全程叫Bourne shell
bash 一种对bsh在功能上进行扩展的shell,几乎可以涵盖shell所需要的所有功能
ksh 一种与bsh兼容的编程shell,增加了很多特性,常见于Unix操作系统
tcsh 一种具有C语言风格语法结构的shell,常见于嵌入式开发
zsh 一种结合了bash、ksh和tsh的特点,同时提供了高级编程特性的高级shell
sh 绝大部分Linux发行版中,作为软链接指向其他shell(默认是bash)
# 查看系统默认的shell
root@luckydog:~# cat /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/bash
/usr/bin/bash
/bin/rbash
/usr/bin/rbash
/bin/dash
/usr/bin/dash

几乎所有的Linux发行版默认shell是bash shell

帮助开发人员或系统管理员将复杂而又反复的操作放在一个文件中,通过简单的步执行操作完成相应任务,从而解放他们的负担。

1.2 shell语法

1.2.1 shell脚本定义和执行

  1. 执行shell脚本文件,一般以.sh作为后缀名,也可不加

  2. 编写代码

    ex.sh

    # 定义开头,用于指定当前脚本文件的shell解释器的类型
    # 如果不写,则使用默认的shell解释器
    #!/bin/bash
    pwd
  3. 修改权限

    chmod +x ex.sh
  4. 执行文件

    ./ex.sh
    # 或者
    bash ex.sh

1.2.2 变量

  1. 自定义变量

    #!/bin/bash
    # shell中变量没有数据类型
    # 变量名=变量值
    NUM = 100;
    # 显示变量
    echo $NUM
    # 清除变量
    unset $NUM
    # 再显示变量,变量清除后,会显示为空
    echo $NUM

    输出结果

    10
    **********
  2. 从终端获取变量

    #!/bin/bash
    read str
    echo "str = $str"
    # 创建只读变量
    readonly n=999
    echo $n
    # 只读变量不能被修改
    n=666
    echo n

    输出结果

    123
    str = 123
    999
    02_read.sh: line 11: n: is read only
  3. 环境变量

    shell 在开始执行时就已经定义了一些和系统的工作环境有头的变量,我们在 shell 中可以直接使用$name 引用

    定义:一般在~/.bashrc/etc/profile文件中,使用export设置,也允许用户更改

    # 一般来讲,环境变量都是大写
    VARNAME=VAR
    export VARNAME

    方法一 :临时设置

    #在终端执行命令
    MYVAL=999
    export MYVAL

    方法二:永久设置

    需要再配置文件中(~/.bashrc/etc/profile)中进行设置即可,设置完毕后需要通过source命令配置文件立即生效

    source ~/.bashrc
    #!/bin/bash
    echo "You are welcome to use bash"
    echo "current work dirctory is $PWD"
    echo "the host name is $HOSTNAME"
    echo "your home dir $HOME"
    echo "Your shell is $SHELL"

    输出结果

    You are welcome to use bash
    current work dirctory is D:/04_Dev/06_Shell/01_概述
    the host name is DESKTOP-TF3PRFT
    your home dir C:/Users/zheng
    Your shell is /bin/sh
  4. 预设变量

    $#: 传给shel脚本参数的数量

    $*: 传给shel脚木参数的内容
    $1、$2、$3、…、$9:运行脚本时传递给其的参数,用空格隔开
    $?: 命令执行后返回的状态

    $? 用于检査上一个命令执行是否正确(在Linux中,命令退出状态为0表示该命令正确执行,任何非0值表示命令出错)。

    $0 : 当前执行的进程名
    $$ : 当前进程的进程号
    $$变量最常见的用途是用作临时文件的名字以保证临时文件不会重复

    #!/bin/bash
    #位置变量$0- $9保存从终端输入的每一个参数
    echo "\$0 = $0"
    echo "\$1 = $1"
    echo "\$2 = $2"
    echo "\$3 = $3"
    echo "\$4 = $4"
    echo "\$5 = $5"
    echo "\$6 = $6"
    echo "\$7 = $7"
    echo "\$8 = $8"
    echo "\$9 = $9"
    #如果超过9,需要加大括号
    echo "\$10 = ${10}"
    #$#:保存命令行传入的参数的个数,不包括$
    echo "\$# = $#"
    #$@或者$*: 保存所有的命令行传入的参数,但是不包括$0
    echo "\$@ = $@"
    echo "\$* = $*"
    # $? 返回上一个命令执行的结果,成功返回0,不成功返回非0
    echo "\$? = $?"
    # $$获取当前进程进程号
    echo "\$$ = $$"

    输出结果

    $ bash 04_var_\$.sh 1 2 3 4 56 4 8 6 47 8 66
    $0 = 04_var_$.sh
    $1 = 1
    $2 = 2
    $3 = 3
    $4 = 4
    $5 = 56
    $6 = 4
    $7 = 8
    $8 = 6
    $9 = 47
    $10 = 8
    $# = 11
    $@ = 1 2 3 4 56 4 8 6 47 8 66
    $* = 1 2 3 4 56 4 8 6 47 8 66
    $? = 0
    $$ = 10300
  5. 特殊用法

    #!/bin/bash
    name="zhangsan"
    string1="good morning ${name}"
    # 单引号中的特殊字符都会失去意义
    string2='good morning ${name}'
    echo $string1
    echo $string2
    # 反引号,获取一个shell命令的输出结果
    echo "today is date"
    echo "today is `date`"
    # 转义字符,使用时需要再echo后面加上-e
    echo "****************"
    echo "this is a \n test"
    echo -e "this is a \ntest"
    echo "****************"
    # 小括号和大括号的区别
    # 小括号由子shell完成,不会修改当前shell中的变量值
    num=100
    (num=999; echo "1. $num";)
    echo 1: $num
    # 大括号由当前shell执行,会修改当前变量
    { num=666; echo "2. $num"; }
    echo 2: $num

    输出结果

    good morning zhangsan
    good morning ${name}
    today is date
    today is Wed Feb 21 11:38:50 中国标准时间 2024
    ****************
    this is a \n test
    this is a
    test
    ****************
    1.999
    1: 100
    2. 666
    2: 666

1.2.3 条件测试语句

在与 shel 脚本时,经常遇到的问题就是判断字符串是合相等,可能还要检查文件状态或进行数字测试,只有这些测试完成才能做下一步动作。

test命令:用于测试字符串、文件状态和数字

test 命令有两种格式:
1. test condition
2. [ condition ] # 使用方括号时,要注意在条件两边加上空格
shell 脚本中的条件测试如下:
文件测试、字符串测试、数字测试、复合测试
参数 说明
-e 文件名 如果文件存在则为真
-r 文件名 如果文件存在且可读则为真
-w 文件名 如果文件存在且可写则为真
-x 文件名 如果文件存在且可执行则为真
-s 文件名 如果文件存在且至少有一个字符则为真
-d 文件名 如果文件存在且为目录则为真
-f 文件名 如果文件存在且为普通文件则为真
-c 文件名 如果文件存在且为字符型特殊文件则为真
-b 文件名 如果文件存在且为块特殊文件则为真
-a 与运算
-o 或运算
非运算
  1. 文件测试

    #!/bin/bash
    echo "please input a file name"
    read FILE
    test -e $FILE
    echo "存在?$?"
    test -s $FILE
    echo "非空?$?"
    [ -r $FILE ]
    echo "可读?$?"
    [ -w $FILE ]
    echo "可写?$?"
    [ -x $FILE ]
    echo "可执行?$?"
    test -b $FILE
    echo "块设备文件?$?"
    test -c $FILE
    echo "字符设备文件?$?"
    test -d $FILE
    echo "目录文件?$?"
    test -f $FILE
    echo "普通文件?$?"
    test -L $FILE
    echo "软链接文件?$?"
    test -S $FILE
    echo "套接字文件?$?"
    test -p $FILE
    echo "管道文件?$?"

    输出结果

    $ ./06_condition_test.sh
    please input a file name
    a
    存在?1
    非空?1
    可读?1
    可写?1
    可执行?1
    块设备文件?1
    字符设备文件?1
    目录文件?1
    普通文件?1
    软链接文件?1
    套接字文件?1
    管道文件?1

    在shell中,0代表是存在,非0代表不存在

  2. 字符串测试

s1 = s2 # 测试两个字符串是否完全一样
s1 != s2 #测试两个字符串是否有差异
-z s1 # 测试s1字符串的长度是否为0
-n s1 # 测试s1字符串长度是否不为0
#!/bin/bash
test "hello" = "hello"
echo "相等? $?"
test "hello" = "hella"
echo "相等? $?"
test -z "hello"
echo "长度是否为0? $?"
test -n "hello"
echo "长度是否不为0? $?"

输出结果

$ ./07_string_test.sh
相等? 0
相等? 1
长度是否为0? 1
长度是否不为0? 0
  1. 数字测试

    a -eq b # 测试a与b是否相等
    a -ne b # 测试a与b是否不相等
    a -gt b # 测试a是否大干 b
    a -ge b # 测试a是否大于等于 b
    a -lt b # 测试a是告小于 b
    a -le b # 测试a是否小于等于 b
    #!/bin/bash
    echo "please input two numbers >>>"
    read NUM1 NUM2
    test $NUM1 -eq $NUM2
    echo "相等? $?"
    test $NUM1 -ne $NUM2
    echo "不相等? $?"
    test $NUM1 -gt $NUM2
    echo "大于? $?"
    test $NUM1 -ge $NUM2
    echo "大于等于? $?"
    test $NUM1 -lt $NUM2
    echo "小于? $?"
    test $NUM1 -le $NUM2
    echo "小于等于? $?"

    输出结果

    $ ./08_num_test.sh
    please input two numbers >>>
    1 2
    相等? 1
    不相等? 0
    大于? 1
    大于等于? 1
    小于? 0
    小于等于? 0
  2. 复合测试

    shell提供了两种操作方式:命令执行控制和多重条件判定

    命令执行控制

    命令符号 说明 操作
    && 与操作 command1 && command2
    || 或操作 command1 || command2

    多重条件判定

    Shell 提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为: ! 最高, -a 次之, -o 最低。

    #!/bin/bash
    num=100
    #判断0<=num<= 200
    test $num -ge 0 && test $num -le 200
    test $num -ge 0 -a $num -le 200
    echo "判断0<=num<= 200 $?"
    #判断num<=0 或者 num >= 200
    test $num -le 0 || test $num -ge 200
    echo "判断num<=0 或者 num >= 200 $?"
    file="file.txt"
    #判断文件是否不是普通文件
    test ! -f $file
    echo "判断文件是否不是普通文件 $?"

    输出结果

    判断0<=num<= 200 0
    判断num<=0 或者 num >= 200 1
    判断文件是否不是普通文件 0

1.2.4 控制语句

  1. if 语句

    if [ 条件1 ]; then
    执行第一段程序
    else
    执行第二段程序
    fi
    if [ 条件1 ];then
    执行第一段程序
    elif [ 条件2 ];then
    执行第二段程序
    else
    执行第三段程序
    fi
    #!/bin/bash
    read NUM
    echo $NUM
    if [ $NUM -ge 50 ]; then
    echo "num 大于50"
    elif [ $NUM -le 50 ]; then
    echo "num 小于50"
    else
    echo "num 等于50"
    fi

    输出结果

    $ ./10_if.sh
    10
    输入的数字为10
    num 小于50
  2. case语句

    case 变量 in
    变量1)
    commands;;
    变量2)
    commands;;
    变量3)
    commands;;
    *)
    default commands;;
    esac
    #!/bin/bash
    read USER
    case ${USER} in
    mysql)
    echo "current user is mysql";;
    root)
    echo "current user is root";;
    *)
    echo "unknown user.";;
    esac

    输出结果

    $ ./11_case.sh
    mysql
    current user is mysql
  3. for 语句

    for var in list
    do
    commands
    done
    for var in list; do
    commands
    done

    12_for.sh

    #!/bin/bash
    # for 循环的变量之前不能加$, (如item就不能加$)
    for item in {"Hello World!",a,bc,1372}; do
    echo "${item}"
    done

    输出结果

    $ ./12_for.sh
    Hello World!
    a
    bc
    1372

    13_for02.sh

    #!/bin/bash
    for name in `ls`; do
    echo "$name"
    # 加入变量判断,可以对文件进行过滤
    done

    输出结果

    $ ./13_for02.sh
    01_var.sh
    02_read.sh
    03_env_var.sh
    04_var_$.sh
    05_var_spec.sh
    06_condition_test.sh
    07_string_test.sh
    08_num_test.sh
    09_com_test.sh
    10_if.sh
    11_case.sh
    12_for.sh
    13_for02.sh
    #!/bin/bash
    for file in ./*
    do
    if [[ ${file##*.} = sh ]]
    then
    echo "sh文件:$file"
    elif [[ ${file##*.} = txt ]]
    then
    echo "txt文件:$file"
    fi
    done

    输出结果

    $ ./script07.sh
    txt文件:./fruitlist.txt
    sh文件:./get-docker.sh
    sh文件:./script01.sh
    sh文件:./script02.sh
    sh文件:./script03.sh
    sh文件:./script04.sh
    sh文件:./script05.sh
    sh文件:./script06.sh
    sh文件:./script07.sh
  4. while循环

    while [ command ]
    do
    commands
    done

    14_while.sh

    #!/bin/bash
    i=1
    while [ $i -le 10 ]
    do
    echo "the number is $i"
    ((i = i + 1))
    done
    $ ./14_while.sh
    the number is 1
    the number is 2
    the number is 3
    the number is 4
    the number is 5
    the number is 6
    the number is 7
    the number is 8
    the number is 9
    the number is 10
  5. until循环

    until 条件不成立就执行循环体,刚好与while相反

    #!/bin/bash
    # 定义整型的i和整型的s
    declare -i i
    declare -i s
    # 当i不等于101的时候,执行循环体
    until [ "$i" = "101" ]; do
    s+=i;
    i=i+1;
    done
    echo "The count is $s"

    输出结果

    $ ./15_until.sh
    The count is 5050
  6. 、break和continue

    break 命令跳出循环体

    continue 只是跳出本次循环,而不是跳出整个循环体,跳出本次后,下个循环接着运行

    #!/bin/bash
    for ((i=0;i<10;i++)); do
    if [ $i -ge 5 ]; then
    echo "当前值为 $i"
    break
    fi
    done

    输出结果

    $ ./16_break.sh
    当前值为 5
    #!/bin/bash
    for ((i=0;i<10;i++)); do
    if [ $i -ge 5 ]; then
    echo "当前值为 $i"
    continue
    fi
    done

    输出结果

    $ ./17_contunue.sh
    当前值为 5
    当前值为 6
    当前值为 7
    当前值为 8
    当前值为 9

1.2.5 shell函数

​ 有些脚本段间互相重复,如果能只写一次代码决而在任何地方都能引用那就提高了代码的可更用性。shell 允许将一组命令集或语句形成一个可用块,这些块称为shell 函数。

#!/bin/bash
# 由于shell中没有主函数一说,所以一般函数定义在整个代码的最上边
function name () {
echo "hello world" # arguments are accessible through $1, $2,...
}
# 调用函数
name

输出结果

$ ./18_fun.sh
hello world

19_fun_arg.sh

#!/bin/bash
function name () {
# shell 函数传参,不能在函数后面的括号定义,而是使用 $1, $2,...
echo "$1"
echo "$2"
}
function add () {
A=$1
B=$2
SUM=`expr $A + $B`
return $SUM
}
name 1111 2222
add 100 200
# 函数的返回值可以通过这个方式获取,但是$?只能获取255以内的值
echo "$?"
# 如果需要获取SUM的值,可以直接用下面的方式
# 因为在同一个shell脚本中,除了小括号()中定义的变量,只要不做任何其他修饰,都是全局变量
echo "SUM = $SUM"

输出结果

$ ./19_fun_arg.sh
1111
2222
44
SUM = 300
posted @   Yasuo_Hasaki  阅读(17)  评论(0编辑  收藏  举报
//雪花飘落效果
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起