嵌入式学习笔记(十一) --shell脚本编程

2019-07-13 06:55发布

总结一句话来说,shell脚本编程 = 基本命令 + 变量 + 语句。看起来没有什么特殊的地方,那就试着分析下吧!
本章内容
  • shell与shell脚本区分
  • shell变量的类型
  • shell语句
  • 函数


一、什么是shell?它和shell脚本有什么区别?

shell英文单词shell可直译为“贝壳”。“贝壳”是动物作为外在保护的一种工具。可以这样认为,Linux中的shell就是Linux内核的一个外层保护工具,并负责完成用户与内核之间的交互。总括,shell是linux命令集的概称,是属于命令行的人机界面。
shell脚本shell脚本语言是解释型语言,shell脚本本质是shell命令的有序集合。可以说,sell命令是作为sell脚本的一部分,sell脚本是在sell命令基础上的进一步抽象。


二、关于shell变量

shell允许用户建立变量存储数据,但不支持数据类型(整型、字符、浮点型),将任何赋给变量的值都解释为一串字符。

通常分成以下四种类型变量:1) 用户自定义变量 : 顾名思义,也叫作本地变量,只在当前shell中生效2) 位置变量即命令行参数:  变量中保存的是和系统操作环境相关的数据
3) 预定义变量 : Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
4) 环境变量:用来向脚本当中传递参数或数据,变量名不能自定义,变量作用是固定的。用户自定义变量          1) 在shell编程中通常使用全大写变量,方便识别      $ COUNT=1 2) 变量的调用:在变量前加$ $ echo $HOME 3) Linux Shell/bash从右向左赋值 $Y=y $ X=$Y $ echo $X y 4) 使用unset命令删除变量的赋值 $ Z=hello $ echo $Z hello $ unset Z $ echo $Z 位置变量 $0 与键入的命令行一样,包含脚本文件名 $1,$2,……$9 分别包含第一个到第九个命令行参数 $# 包含命令行参数的个数 $@ 包含所有命令行参数:“$1,$2,……$9” $? 包含前一个命令的退出状态 $* 包含所有命令行参数:“$1,$2,……$9” $$ 包含正在执行进程的ID号 常用shell环境变量 HOME: /etc/passwd文件中列出的用户主目录 IFS:Internal Field Separator, 默认为空格,tab及换行符 PATH :shell搜索路径 PS1,PS2:默认提示符($)及换行提示符(>) TERM:终端类型,常用的有vt100,ansi,vt200,xterm等


三、shell程序的语句

shell 程序由零或多条shell语句构成。 shell语句包括三类:说明性语句、功能性语句和结构性语句。
  1. 说明性语句:     以#号开始到该行结束,不被解释执行
  2. 功能性语句:      任意的shell命令、用户程序或其它shell程序。
  3. 结构性语句:     条件测试语句、多路分支语句、循环语句、循环控制语句等。   

【1】说明性语句 注释行可以出现在程序中的任何位置,既可以单独占用一行, 也可以接在执行语句的后面. 以#号开始到所在行的行尾部分,都不被解释执行. 例如: #! /bin/sh # ------> 告诉OS用哪种类型的shell来解释执行该程序 # 本程序说明 # command_1 command_2 # command_2的语句说明 …… # 下面程序段的说明 command_m …… command_n # commandn_语句的说明 …… 【2】常用功能性语句 (1) 常用功能性语句(命令) read从标准输入读入一行, 并赋值给后面的变量,其语法为: read var 把读入的数据全部赋给var read var1 var2 var3 把读入行中的第一个单词(word)赋给var1, 第二个单词赋给var2, ……把其余所有的词赋给最后一个变量. 如果执行read语句时标准输入无数据, 则程序在此停留等侯, 直到数据的到来或被终止运行。 (2) 应用实例 # example1 for read echo "Input your name: c" read username echo "Your name is $username" #example2 for read echo "Input date with format yyyy mm dd: c" read year month day echo "Today is $year/$month/$day, right?" echo "Press enter to confirm and continuec" read answer echo "I know the date, bye!" (3) expr命令 算术运算命令expr主要用于进行简单的整数运算,包括加(+)、减(-)、乘(*)、整除(/)和求模(%)等操作。 例如: $ expr 12 + 5 * 3 反斜线去掉*号的元字符含义 27 $ expr 3 - 8 / 2 -1 $ num=9 $ sum=`expr $num * 6 ` 反撇号引用命令的运行结果 $ echo $sum 54
对于结构性语句,可分为条件测试语句、多路分支语句、循环语句、循环控制语句等。这里不一一举例了,只是介绍下这些语句的使用方法。 (1)条件语句 if…then…fi 语法结构: if 表达式 then 命令表 fi 1)如果表达式为真, 则执行命令表中的命令; 否则退出if语句, 即执行fi后面的语句。 2)if和fi是条件语句的语句括号, 必须成对使用; 3)命令表中的命令可以是一条, 也可以是若干条。 (2) if…then…else…fi 语法结构为: if 表达式 then 命令表1 else 命令表2 fi 如果表达式为真, 则执行命令表1中的命令, 再退出if语句; 否则执行命令表2中的语句, 再退出if语句. 注意: 无论表达式是否为真, 都有语句要执行. (1)多路分支语句 case…esac 多路分支语句case用于多重条件测试, 语法结构清晰自然. 其语法为: case 字符串变量 in 模式1) 命令表1 ;; 模式2 | 模式3) 命令表2 ;; …… 模式n) 命令表n ;; esac 注: 1)case语句只能检测字符串变量 2)各模式中可用文件名元字符,以右括号结束 3)一次可以匹配多个模式用“|”分开 4)命令表以单独的双分号行结束,退出case语句 5)模式 n常写为字符* 表示所有其它模式 6)最后一个双分号行可以省略
(1)循环语句for 1)当循环次数已知或确定时,使用for循环语句来多次执行一条或一组命令。 循环体由语句括号do和done来限定。格式为: for 变量名 in 单词表 do 命令表 done 2)变量依次取单词表中的各个单词, 每取一次单词, 就执行一次循环体中的命令. 循环次数由单词表中的单词数确定. 命令表中的命令可以是一条, 也可以是由分号或换行符分开的多条。 3)如果单词表是命令行上的所有位置参数时, 可以在for语句中省略 “in 单词表” 部分。
【1】循环语句while的用法 (1)语法结构为: while 命令或表达式 do 命令表 done 1)while语句首先测试其后的命令或表达式的值,如果为真,就执行一次循环体中的命令, 然后再测试该命令或表达式的值,执行循环体,直到该命令或表达式为假时退出循环。 2)while语句的退出状态为命令表中被执行的最后一条命令的退出状态。【2】循环控制语句 (1) break 和 continue break n 则跳出n层; continue语句则马上转到最近一层循环语句的下一轮循环上, continue n则转到最近n层循环语句的下一轮循环上. 实例. 程序prog7的用法为: prog7 整数 整数 整数 … 参数个数不确定, 范围为1~10个, 每个参数都是正整数。


四、函数

shell函数面向过程,从函数的定义与调用方面来讲。函数调用格式:
方式1:
value_name=`function_name  [arg1 arg2 … ]`
函数的所有标准输出都传递给了主程序的变量
方式2:
function_name  [arg1  arg2  …  ]
echo   $?
获取函数的返回的状态
实例: check_user( ) { #查找已登录的指定用户 user=`who | grep $1 | wc -l` if [ $user –eq 0 ] then return 0 #未找到指定用户 else return 1 #找到指定用户 fi } while true # MAIN, Main, main: program begin here do echo "Input username: c" read uname check_user $uname # 调用函数, 并传递参数uname if [ $? –eq 1 ] # $?为函数返回值 then echo "user $uname online" else echo "user $uname offline" fi done
PS:关于函数中定义的变量,默认是全局的(在脚本的其他任何地方都能够访问该变量)。要想只能在声明变量的作用域内访问,需要加Local 声明一下Local variable_name =value