![嵌入式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=1739296954-ECPGGbr54ltSHgoq58eyVE9PqMls8aZU-0-35d5e8a4c9ada8874b1e7505859214e6)
第1行的“#!”是一个约定的标记,告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell;后面的“/bin/bash”指明解释器的位置。
第2行的echo命令用于向标准输出设备(如显示器)输出数据。在.sh文件中使用命令与在终端直接输入命令的效果是一样的。第2行的“#”及其后面的内容是注释。Shell脚本示例如下:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_31_3.jpg?sign=1739296954-n5Px9QfQvjUimyq3fi8gHnkmsvTblgow-0-d6be49c32eea8fed3d187f5f1ceed250)
上述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=1739296954-C4JZi8cFrCjvd6Ig4UmvABsZMoOHthW2-0-795115916ca2d2ee67acbfc62ec7a563)
2)环境变量
Shell的环境变量是所有Shell程序都可以使用的变量,会影响所有脚本的执行结果。Shell的环境变量如表2.11所示。
表2.11 Shell的环境变量
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_32_2.jpg?sign=1739296954-32kzxFujRqy3Y8n805hh7LJ40L3r37ex-0-0b1e2625a27dba7d23d827a15b68934c)
3)设置变量
变量的设置规则如下:
(1)变量名称可以由字母、数字或下画线组成,但不能以数字开头,环境变量名建议大写,便于区分。
(2)变量的默认类型都是字符串型,如果要进行数值运算,则必须指定变量类型为数值型。
(3)变量用等号连接值,等号左右两侧不能有空格。
(4)如果变量的值有空格,则需要使用单引号或者双引号包括。
4)定义变量
Shell支持3种定义变量的方式,例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_33_1.jpg?sign=1739296954-jrjkI2EUAeykyodjstrTRpFEP1nepFk5-0-a9e590bafa972eb4b2689149ed223f08)
输出为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_33_2.jpg?sign=1739296954-eBaiXtmVGAMc91eG8LrDalFFPNJ4jW2z-0-e9b1188374a004f4eb870054bd7a2008)
variable是变量名,Stone是赋给变量的值。如果赋给变量的值中不包含空白符,则可以不使用引号;如果赋给变量的值中包含空白符,则必须使用引号包围起来。单引号和双引号是有区别的,当使用单引号包围变量时,单引号里面是什么就输出什么,这种方式适合纯字符串的情况,即不希望解析变量、命令等;当使用双引号包围变量时,输出时会先解析里面的变量和命令,这种方式适合字符串中附带有变量和命令,并且希望解析其中的变量和定义后再输出的变量定义。
5)使用变量
使用一个定义过的变量,只需要在变量名前面加符号“$”即可,例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_33_3.jpg?sign=1739296954-dLy7QZdjE91UxKU32kribGThSVgwB7Fk-0-dfb567b32faee92777529d59632c8455)
运行结果为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_33_4.jpg?sign=1739296954-D20rJjgqmfJWKWXXNr2kcrNzGB1LlfZN-0-5630ce3f3d500ba436474deff76fe9a7)
变量名外面的花括号是可选的,加花括号可以帮助解释器识别变量的边界。
6)修改变量的值
已定义的变量可以重新被赋值,例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_33_5.jpg?sign=1739296954-v6p2mCt5XYB1f6smfuACzFyybhJoijU9-0-191ace1090354434b7222e815278b6e7)
运行结果为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_34_1.jpg?sign=1739296954-3r7GVccusdl84fmlwRNdzfDP9KLZ9yhV-0-1e858d21291bca229af4b709925fb2d0)
7)删除变量
使用unset命令可以删除变量,例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_34_2.jpg?sign=1739296954-U7Yeua3SPevGPyrmJTq1ORz5QLCqIqGE-0-363504aa54d1ce66466c4ce399b38d55)
变量被删除后不能再次使用;unset命令不能删除只读变量。
2.1.5.4 Shell的流程控制
(1)if语句。if语句的格式为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_34_3.jpg?sign=1739296954-NpEYkq1itvqXk1kH6L7hn332uZAfvKBl-0-6c9743a7c19886454ce41f587350548f)
举例如下:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_34_4.jpg?sign=1739296954-C1W2Sn2qxnwRjvBVqgAQ0LLSYmorfDKW-0-913068b13ecec3577f8ef79e6fb6fe07)
输出结果为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_34_5.jpg?sign=1739296954-sgP7ILh84mRRexUAO1QCPXP82FCQGDU2-0-9e753d4138622b85b7b8b12fede68714)
(2)for语句。for语句的格式为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_34_6.jpg?sign=1739296954-wfIiNSrkOiMvrMP445lDIf3nVVxIj2t6-0-727b0a98d100e9056c6beebfc7dc8c46)
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_1.jpg?sign=1739296954-4im9bu8g2frSJGxRO4pORld2IwxzfSXO-0-fe88c49e97f8adfb439f371ba4887916)
例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_2.jpg?sign=1739296954-8XZ386puX5dboOxvl7NN7EDN5XhUto5l-0-746858d9bd109b527a9c61d99befdf1e)
输出结果为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_3.jpg?sign=1739296954-Lh8r26GVJ3voPRG2p8WS15s2u1mShC7e-0-6ebd3fcb24002f79134322f55e6c15aa)
(3)while语句。while语句的格式为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_4.jpg?sign=1739296954-JTGXNtx66dIKdUUIcIMRnNRwzw4b2wD7-0-b1b89f1aa4c92300bde1d9ad9ce21f47)
例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_5.jpg?sign=1739296954-bm7krjD2qDUhbrIrTgKZi1VwwBaVJ0cG-0-ba9b99929a651cfaf73efad7fd29c896)
输出结果为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_6.jpg?sign=1739296954-LfGpOFKR1XofvQyZnTpCXgndeJNQv5wC-0-ace012b95f3ed1e87493de13160eaaf0)
(4)case语句。case语句的格式为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_35_7.jpg?sign=1739296954-BdNvFPU6HklSXyXTH8iNA4mT2KpifMG4-0-4a0de26c389f0b20c2eef3b1758b3c14)
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_36_1.jpg?sign=1739296954-gZgb2CiKE4uRIpivtNNqmzHvwt2NQNlQ-0-068a9b691a3174079bc88ea27de7a290)
例如:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_36_2.jpg?sign=1739296954-qFCQQbpmffCrLsYMSyX9lOSftD0gQRKq-0-8c57ed5a51f708f725af0559d63f7d72)
输入5,输出结果为:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_36_3.jpg?sign=1739296954-xRME3SGmRghRTevfXQQfOUQe46h6z7lv-0-52f22fcd9d6707b22190c4521c1ebd28)
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=1739296954-aNRYCyQrVrbzq3WaSVla389K45nVXxc5-0-49651b93ffc27c29994d55648bf4f890)
在上述代码中,第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=1739296954-7vxXwtOBL2uUdl7klmFznCqmL9DfSd35-0-7215b9795e748bff58f86b42fac3ae75)
通过这种方式运行脚本,不需要在脚本文件的第一行指定解释器信息。
③更加简洁的方法是运行bash命令。bash是一个外部命令,Shell会在“/bin”目录中找到对应的应用程序,即“/bin/bash”。修改如下:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_37_2.jpg?sign=1739296954-ksEElEAOgroMXTopjC1N2x4TZ4UidH3O-0-61c1f4783f19586204be82b97a52c53d)
(2)在当前进程中运行Shell脚本。需要用到source命令,source命令会读取脚本文件中的代码,并依次执行所有语句。source命令的用法如下:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_37_3.jpg?sign=1739296954-lOz5MtHNiCofLlWGbIuJRUL3qVr3n7AM-0-459df6bc1921ef9081955cc1cb83a98e)
例如,使用source命令运行test.sh,代码如下:
![](https://epubservercos.yuewen.com/05A69C/23020642901652606/epubprivate/OEBPS/Images/42374_37_4.jpg?sign=1739296954-Nga6y9O5K4aFBc8SrBxVWTPF5kTGleYu-0-04d80811bc6556314c3b101301fb014f)