![嵌入式Linux开发技术](https://wfqqreader-1252317822.image.myqcloud.com/cover/138/43738138/b_43738138.jpg)
2.1.5 Shell脚本
2.1.5.1 Shell脚本简介
Shell脚本是指将各类命令预先放在一个文件中,方便一次性执行的程序文件,使用了Linux、UNIX中的命令。Shell提供了数组、循环、条件和逻辑判断等重要功能,使用者可以直接以Shell来写程序,而不必使用类似C语言等传统程序语言的语法。
Shell是一个命令行解释器,按照一定的语法将输入的命令加以解释并传给系统,为用户提供了一个向Linux发送请求以便运行程序的接口系统级程序,用户可以用Shell来启动、挂起、停止,甚至编写一些程序。
Shell既是一种命令语言,又是一种程序设计语言。作为程序设计语言,Shell定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,如循环结构和分支结构。作为命令语言,虽然Shell不是Linux系统内核的一部分,但它调用了系统内核的大部分功能来执行程序、创建文档,并以并行的方式协调各个程序的运行。
2.1.5.2 创建Shell脚本
打开文本编辑器,新建一个文本文件并命名为test.sh。在test.sh中输入以下代码:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_31_2.jpg?sign=1738891925-Dgz1Tp3y72iAgOMwfxiNOf24TSXIijHY-0-d2fd0db2ee6f55abd581dac1e0e017ea)
第1行的“#!”是一个约定的标记,告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell;后面的“/bin/bash”指明解释器的位置。
第2行的echo命令用于向标准输出设备(如显示器)输出数据。在.sh文件中使用命令与在终端直接输入命令的效果是一样的。第2行的“#”及其后面的内容是注释。Shell脚本示例如下:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_31_3.jpg?sign=1738891925-9m31OExuT3rjMmuy2KyFSib8jzj95vRb-0-c9fe32972284a117d9f9b61f5fbaf774)
上述Shell脚本示例的第4行表示从终端读取用户输入的数据,并赋值给PERSON变量。read命令用来从标准输入设备(鼠标、键盘)中读取数据;第5行表示输出PERSON变量的内容,注意在变量名前边要加上“$”,否则会将变量名当成字符串来处理。
2.1.5.3 Shell变量
1)系统变量
Shell的系统变量主要在判断参数和命令返回值时使用,包括脚本和函数的参数,以及脚本和函数的返回值。Shell的系统变量如表2.10所示。
表2.10 Shell的系统变量
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_32_1.jpg?sign=1738891925-YTsrrXgVPToxPCkHCMvFpBqcCdW78NP2-0-6fe7feb51d219aba3f625b72f6d210e7)
2)环境变量
Shell的环境变量是所有Shell程序都可以使用的变量,会影响所有脚本的执行结果。Shell的环境变量如表2.11所示。
表2.11 Shell的环境变量
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_32_2.jpg?sign=1738891925-wfprUz4J194MlTI4OAmHgDVFou2EzLtJ-0-c146071a2515b013cb042ecefdfaa13f)
3)设置变量
变量的设置规则如下:
(1)变量名称可以由字母、数字或下画线组成,但不能以数字开头,环境变量名建议大写,便于区分。
(2)变量的默认类型都是字符串型,如果要进行数值运算,则必须指定变量类型为数值型。
(3)变量用等号连接值,等号左右两侧不能有空格。
(4)如果变量的值有空格,则需要使用单引号或者双引号包括。
4)定义变量
Shell支持3种定义变量的方式,例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_33_1.jpg?sign=1738891925-NHiDFLLWI7ZrTazbZ9ZZ6fw1dEx7BgFZ-0-1dbc153880c9af74de01111124f191ec)
输出为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_33_2.jpg?sign=1738891925-aRoTKbNmo30MQSDhBnRlNIbXp2fmebN4-0-95f8063afcb6b59d809d0b282cdc6b30)
variable是变量名,Stone是赋给变量的值。如果赋给变量的值中不包含空白符,则可以不使用引号;如果赋给变量的值中包含空白符,则必须使用引号包围起来。单引号和双引号是有区别的,当使用单引号包围变量时,单引号里面是什么就输出什么,这种方式适合纯字符串的情况,即不希望解析变量、命令等;当使用双引号包围变量时,输出时会先解析里面的变量和命令,这种方式适合字符串中附带有变量和命令,并且希望解析其中的变量和定义后再输出的变量定义。
5)使用变量
使用一个定义过的变量,只需要在变量名前面加符号“$”即可,例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_33_3.jpg?sign=1738891925-o4h8HA8QuqTnQe8sYCX86cxYumzbXTWW-0-2b95bb4e2557140a3ff247ed88a39e95)
运行结果为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_33_4.jpg?sign=1738891925-sMyFO4UKSiHmDawLP67ZgbeftOIarDfW-0-8430dc9dd1123c87efa696af7e74b98a)
变量名外面的花括号是可选的,加花括号可以帮助解释器识别变量的边界。
6)修改变量的值
已定义的变量可以重新被赋值,例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_33_5.jpg?sign=1738891925-vhVUKnDZwOMixh6dPXnTAEzTrAp6QvZ1-0-504e684a3f037dd9149ee7f7620fc2bc)
运行结果为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_34_1.jpg?sign=1738891925-m46qGYibYeYhgLxIci1LvdDQKA8uGB4E-0-c60b45eeea6b0a35f7d0dc79bb6ffb21)
7)删除变量
使用unset命令可以删除变量,例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_34_2.jpg?sign=1738891925-7atE7WPLTE3AssnwnfITIPXMCTrifPcg-0-9fba68fbc1e567a29a00546bd739d4b5)
变量被删除后不能再次使用;unset命令不能删除只读变量。
2.1.5.4 Shell的流程控制
(1)if语句。if语句的格式为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_34_3.jpg?sign=1738891925-EddNaFWYrFuhG1H1QOsDiuAAFv8Ob0kf-0-f3bf791bc7f10156d61a8a4c43763126)
举例如下:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_34_4.jpg?sign=1738891925-PKnhbkYPuHIXgGZ2mBijR4okCxAPQKRY-0-6a08f7e355703fe8b8c950caca876129)
输出结果为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_34_5.jpg?sign=1738891925-luhUHuVFFaXZWM1F4HWmhEkL6eE0ampM-0-0082ffaa2c23276dc88aa597fa9222d2)
(2)for语句。for语句的格式为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_34_6.jpg?sign=1738891925-1r1duehf8bhNmn5kNDOVJuR2yvuI9wIg-0-938fbc2b4aa042ddeb3c6f98799c63d7)
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_1.jpg?sign=1738891925-guZniqotJmCjiJawJnfpoMf5VSEcYb4i-0-60105ec53ccf667401fd61af16abb9b7)
例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_2.jpg?sign=1738891925-29ndOY1Ba2c2uYgODSk0Blp3aDVRgl5O-0-ebf54f21f4fb21db399b551231bd64b2)
输出结果为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_3.jpg?sign=1738891925-VUCja9kzv3jyBmlaTI3O8KTNdCDbQoOH-0-25be46a72b9674a14c453ee9361798f3)
(3)while语句。while语句的格式为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_4.jpg?sign=1738891925-eheMNSJpFJDoK2I86SGvaQVA2j0M310c-0-8512d32c6a6b7840d6ae08ccefb12592)
例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_5.jpg?sign=1738891925-u0pfe8VckVj01qJ2GmJiGpwgWADKnijb-0-62ecceff2ec90694ea9e53d5bdd9b10d)
输出结果为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_6.jpg?sign=1738891925-5V8cjeTFC2UrSoWqMWeWTV3fzGq8SGWq-0-cbeb1b27c7d5bdab97e6947acedfa2a6)
(4)case语句。case语句的格式为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_7.jpg?sign=1738891925-7UqHhahWD6b9sx36aUmX45ZNNPHYciZ6-0-4b6f79cedaab7c9476cc2aac8fea7988)
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_36_1.jpg?sign=1738891925-t93mwuouTrZ6ffIJ9OQ31UK26bjzvb7L-0-645fb5bee7fd5d79de95edcad44b59be)
例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_36_2.jpg?sign=1738891925-QvEROOXDIqJTvk7B0i2YiREISPAGRDv2-0-3dfefa3f8718387668417ea672c0ef68)
输入5,输出结果为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_36_3.jpg?sign=1738891925-2MFtJEVpAM8DZiLbHEpWwtQnjJtoXckm-0-dc02d8e3c72bc49fe5c048c156d2224f)
2.1.5.5 Shell脚本的执行
运行Shell脚本的方法有两种:一种是在新进程中运行Shell脚本;另一种是在当前的进程中运行Shell脚本。
(1)在新进程中运行Shell脚本。
①将Shell脚本作为程序运行。Shell脚本也是一种解释执行的程序,可以在终端直接调用,如下所示:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_36_4.jpg?sign=1738891925-09FTc327YCAExpS4rR8H4sIXDS8WSz1d-0-555a25544de68babd731619a83fb9fa9)
在上述代码中,第2行中的“chmod+x”表示给test.sh增加执行权限;第3行用来执行当前目录下的test.sh。
②将Shell脚本作为参数传递给Bash解释器。将脚本文件的名字作为参数传递给Bash,例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_37_1.jpg?sign=1738891925-2Pu5YXMMibT53EpCHma7UNfjAYDBSB8W-0-2759b2ff7145aaa25cd4bec82d8a57c0)
通过这种方式运行脚本,不需要在脚本文件的第一行指定解释器信息。
③更加简洁的方法是运行bash命令。bash是一个外部命令,Shell会在“/bin”目录中找到对应的应用程序,即“/bin/bash”。修改如下:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_37_2.jpg?sign=1738891925-iTZFIEyyDQkpIhOOysLPNe0uHp1r2LIo-0-a57d81124b0f732a42c3bfa2833843cd)
(2)在当前进程中运行Shell脚本。需要用到source命令,source命令会读取脚本文件中的代码,并依次执行所有语句。source命令的用法如下:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_37_3.jpg?sign=1738891925-HyWkCvGLMcq1QPFfarPFrsIa20YrLAPa-0-77283224170a8a1d7fa562239dbb6035)
例如,使用source命令运行test.sh,代码如下:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_37_4.jpg?sign=1738891925-flkQKUVJk8MLwPmTXkilV0YDvXeckeMR-0-7cf95033e35f41b9eae11192072fbb2f)