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脚本定义和执行
-
执行shell脚本文件,一般以
.sh
作为后缀名,也可不加 -
编写代码
ex.sh
# 定义开头,用于指定当前脚本文件的shell解释器的类型 # 如果不写,则使用默认的shell解释器 #!/bin/bash pwd -
修改权限
chmod +x ex.sh -
执行文件
./ex.sh # 或者 bash ex.sh
1.2.2 变量
-
自定义变量
#!/bin/bash # shell中变量没有数据类型 # 变量名=变量值 NUM = 100; # 显示变量 echo $NUM # 清除变量 unset $NUM # 再显示变量,变量清除后,会显示为空 echo $NUM 输出结果
10 ********** -
从终端获取变量
#!/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 -
环境变量
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 -
预设变量
$#
: 传给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 -
特殊用法
#!/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 | 或运算 |
! | 非运算 |
-
文件测试
#!/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代表不存在
-
字符串测试
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
-
数字测试
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 -
复合测试
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 控制语句
-
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 -
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 -
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 -
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 -
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 -
、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
本文来自博客园,作者:Yasuo_Hasaki,转载请注明原文链接:https://www.cnblogs.com/hasaki-yasuo/p/18025755
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步