【嵌入式入门学习笔记】-- 五、shell编程

嵌入式入门学习系列笔记索引

一、Linux简介

二、deb软件包管理

三、shell中的特殊字符

四、Linux常用命令

五、shell编程


目录

一、shell与变量

1.shell脚本基础知识

2.shell变量

2.1 用户自定义变量

2.2 位置变量(命令行参数)

2.3 预定义变量

2.4 环境变量

二、shell语句

1.常用功能性语句

1.1 read命令

1.2 expr命令

2.测试语句

test

3.结构性语句

3.1条件语句

3.2多路分支语句

3.3循环语句for

3.4循环语句while

3.5循环控制语句

三、函数

1.shell函数调用

2.函数变量作用域


一、shell与变量

1.shell脚本基础知识

编程语言分为编译型语言和解释型语言,shell脚本语言是解释型语言。

shell脚本本质上就是shell命令的有序集合。

shell编程的基本过程分为三步:

①建立shell文件:包含任意多行操作系统命令或shell命令的文本文件;

②赋予shell文件执行权限:用chmod命令修改权限;

③执行shell文件:直接在命令行上调用shell程序

2.shell变量

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

count=1   #这里的等号前后不要加空格,否则会报错
echo $count
DATE=`date`   #这里的等号前后不要加空格
echo $DATE

Bourne Shell(以.sh为后缀)有如下四种变量:

  • 用户自定义变量
  • 位置变量(命令行参数)
  • 预定义变量
  • 环境变量

2.1 用户自定义变量

用户自定义变量一般全大写,方便识别

COUNT=1

在变量前加$调用变量

echo $HOME

使用unset命令删除变量的赋值

Z=hello
echo $Z

unset Z
echo $Z

2.2 位置变量(命令行参数)

$0 :与键入的命令行一样,包含脚本文件名

$1,$2,.......$9,${10}.....: 分别包含第一个到第十个命令行参数

$#: 包含命令行参数的个数(不包含$0)

$@: 包含所有命令行参数(不包含$0)

$?: 包含前一个命令的推出状态(0表示正常退出)

$*: 包含所有命令行参数(不包含$0)

$$: 包含正在执行的进程ID号

2.3 预定义变量

2.4 环境变量

常用的shell环境变量

HOME:/etc/passwd 文件中列出的用户主目录

IFS:Internal Field Separator,默认为空格,tab及换行符

PATH:shell搜索路径

PS1,PS2:默认提示符($)及换行提示符(>)

TERM:终端类型,常用的有vt100,ansi,vt200,xterm等

二、shell语句

        shell语句包括三类:1.说明性语句,2.功能性语句,3.结构性语句。

       其中,说明性语句以#号开始到该行结束,不被解释执行;功能性语句是任意的shell命令,用户程序或其他shell程序;结构性语句包括条件测试语句、多路分支语句、循环语句、循环控制语句等。

1.常用功能性语句

任意的shell命令、用户程序或其他shell程序

1.1 read命令

read从标准输入读入一行,并赋值给后面的变量,其语法为

read var
#把读入的数据全部赋给var(空格隔开)
read var1 var2 var3  
#如果执行read语句时标准输入无数据,则程序在此停留等候,直到数据的到来或被终止运行

【嵌入式入门学习笔记】-- 五、shell编程_第1张图片

# 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  continue\c"
read  answer
echo "I  know  the  date,  bye!"

1.2 expr命令

        主要用于进行简单的整数运算,包括加(+)、减(-)、乘(\*),整除(/)和求模(%)等操作,例如

> expr  12  +  5  \*  3  # 反斜线去掉*号的元字符含义
27
> expr  3  -  8  /  2  # 运算符号前后要加空格
-1

> num=9
> sum=`expr  $num  \*  6`  # 反撇号引用命令的运行结果
> echo  $sum
54

2.测试语句

test

test语句可测试三种对象: ①字符串 ②整数 ③文件属性

每种测试对象都有若干测试操作符,例如:

test  "$answer"  =  "yes"#  变量answer的值是否为字符串yes
test  $num –eq  18       # 变量num的值是否为整数18
test  -d  tmp            #测试tmp是否为一个目录名

字符串测试

s1 = s2   测试两个字符串的内容是否完全一样

s1 != s2  测试两个字符串的内容是否有差异

-z s1            测试s1 字符串的长度是否为0

-n s1            测试s1 字符串的长度是否不为0

整数测试

a -eq b   测试a 与b 是否相等(equal)

a -ne b  测试a 与b 是否不相等(not equal)

a -gt b   测试a 是否大于b(great than)

a -ge b   测试a 是否大于等于b(great equal)

a -lt b   测试a 是否小于b(less than)

a -le b   测试a 是否小于等于b

文件测试

-d name    测试name 是否为一个目录

-e name    测试一个文件是否存在

-f name     测试name 是否为普通文件

-L name    测试name 是否为符号链接

-r name     测试name 文件是否存在且为可读

-w name    测试name 文件是否存在且为可写

-x name     测试name 文件是否存在且为可执行

-s name     测试name 文件是否存在且其长度不为0

f1 -nt f2     测试文件f1 是否比文件f2 更新

f1 -ot f2     测试文件f1 是否比文件f2 更旧

3.结构性语句

        结构性语句主要根据程序的运行状态、输入数据、变量的取值、控制信号以及运行时间等因素来控制程序的运行流程。

        主要包括:条件测试语句(两路分支)、多路分支语句、循环语句、循环控制语句和后台执行语句等。

3.1条件语句

        这里要注意,在shell中条件为真返回的是0而不是1,那么对于判断符[] 来说,只要符号里面的内容为真即为成功,不要用0 1去理解,容易混肴。

if…then…fi

语法结构:

if  表达式

        then  命令表

fi

  • 如果表达式为真(0), 则执行命令表中的命令; 否则退出if语句, 即执行fi后面的语句。
  • if和fi是条件语句的语句括号, 必须成对使用;
  • 命令表中的命令可以是一条, 也可以是若干条。
#The statement of  if…then…fi                 (注释语句)
if   [  -f   $1  ]         (测试参数是否为文件)
then
	echo "File  $1  exists"                     (引用变量值)
fi
if   [  -d   $HOME/$1  ]                    (测试参数是否为目录)
then 
	echo "File  $1 is  a  directory"       (引用变量值)
fi

if...then...else...fi

语法结构:

if  表达式

        then 命令表1

        else  命令表2

fi

如果表达式为真, 则执行命令表1中的命令, 再退出if语句; 否则执行命令表2中的语句, 再退出if语句.

注意: 无论表达式是否为真, 都有语句要执行.

###test命令测试的条件成立时, 命令返回值为真(0),否则返回值为假(非0).

#方式1
test $name -eq $1
echo $?

#方式2
if test -f $filename
    then
    ......
fi

#方式3,用方括号代替test语句
if [ -f $filename ]     #方括号的首末至少要有一个空格
    then
    ......
fi

3.2多路分支语句

case......esac

语法结构:

case  字符串变量   in          #case语句只能检测字符串变量

        模式1)                #各模式中可用文件名元字符,以右括号结束

                命令表1

                ;;

        模式2|模式3)           #一次可以匹配多个模式,用“ | ”分开

                命令表2

                ;;              #命令表以单独的双分号行结束,推出case语句

        ......

        模式n)                  #模式n常写为字符*  表示所有其他模式

                命令表n

                ;;               #最后一个双分号行可以省略

esac

实例:

# The statement of  case…esac
if   [  $#  -eq  0  ]
then
		echo  "No argument is declared"
		exit
fi
case  $1  in
		file1)
			echo  "User selects file1"
			;;
		file2)
			echo  "User selects file2"
			;;
		*)
			echo  "You must select either file1 or file2!"
			;;
esac

3.3循环语句for

语法格式:

for 变量名 in 单词表

do

        命令表

done

        变量依次取单词表中的各个单词,  每取一次单词, 就执行一次循环体中的命令.  循环次数由单词表中的单词数确定. 命令表中的命令可以是一条, 也可以是由分号或换行符分开的多条。行符分开的多条。

        如果单词表是命令行上的所有位置参数时, 可以在for语句中省略 “in  单词表” 部分。

实例:拷贝当前目录下的所有文件到backup子目录下

# The statement of for…do…done
if  [  !  -d  $HOME/backup  ]
then
	mkdir  $HOME/backup
fi
flist=`ls`           #flist的值是ls的执行结果即当前目录下的文件名
for  file  in  $flist
do
	if   [  $#  =  1  ]
	then
		if   [  $1  =  $file  ]      #命令行上有一个参数时
		then
			echo  "$file  found" ;  exit
		fi
	else                             #命令行上不带参数时
		cp  $file  $HOME/backup
		echo  "$file  copied"
	fi
done
echo   ***Backup  Completed***

3.4循环语句while

语法结构:

while 命令表达式

do

        命令表

done

        while语句首先测试其后的命令或表达式的值,如果为真,就执行一次循环体中的命令,然后再测试该命令或表达式的值,执行循环体,直到该命令或表达式为假时退出循环。

        while语句的退出状态为命令表中被执行的最后一条命令的退出状态。

实例:根据输入批量生成空白文件

# The statement for  while
if [ $# = 2 ]
then
		loop=$2           #根据命令行的第二个参数来确定循环的次数
else
		loop=5
fi
i=1
while  [  $i  -lt   $loop  ]
do
		> $1$i    #建立以第一个参数指定的文件名前缀,例如以“file”开头, 变量i的值结尾的空文件名. 
                  #参见命令cmd  >  file
		i=`expr  $i  +  1`
done

3.5循环控制语句

break和continue

        break n :跳出n层循环

        continue:马上转到最近一层循环语句的下一轮循环上

        continue n:转到最近n层循环语句的下一轮循环上。

实例,检查输入参数中的偶数值,并打印

#!/bin/bash
if  [  $#  =  0  ]
then
		echo  "Numeric  arguments  required"
		exit
fi
if  [  $#  -gt   10  ]
then
		echo  "Only  ten  arguments  allowed"
		exit
fi
for  number              #省略了‘in 单词表’ ,表示number依次取命令行上的所有位置参数
do
		count=`expr  $number  %  2` #count值只能是0或1
		if  [  $count  -eq  1  ]
		then
			continue
		else
			output="$output   $number"  #这样就能输出一个队列了
		fi
done
echo  "Even  numbers:  $output "

三、函数

1.shell函数调用

方式1:

value_name=`function_name  [arg1 arg2 … ]`

函数的所有标准输出都传递给了主程序的变量

方式2:

function_name  [arg1  arg2  …  ]

echo   $?

获取函数的返回的状态

实例

check_user( )    {  #查找已登录的指定用户
	    user=`who  |  grep  $1 | wc -l` #等号两端不能留空格,否则会有警告,具体见shell中的空格
        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

        其中,' | '是管道符,将' | '前面命令的输出作为'|'后面的输入。

        who命令用于显示系统中有哪些使用者正在上面,显示的资料包含了使用者 ID、使用的终端机、从哪边连上来的、上线时间、呆滞时间、CPU 使用量、动作等等。

        grep命令用于查找文件里符合条件的字符串。

         wc指令我们可以计算文件的Byte数、字数、或是列数,若不指定文件名称、或是所给予的文件名为"-",则wc指令会从标准输入设备读取数据。属性:-l或--lines 显示行数。

2.函数变量作用域

全局作用域:在脚本的其他任何地方都能够访问该变量。

局部作用域:只能在声明变量的作用域内访问。

声明局部变量的格式:

                Local variable_name = value

实例

Scope()
{
Local lclvariable =1
Gblvariable = 2
echo “lclavariable in function = $ lclvariable ”
echo “Gblvariable in function = $ Gblvariable ”
}

Scope

echo “lclavariable in function = $ lclvariable ”
echo “Gblvariable in function = $ Gblvariable ”

你可能感兴趣的:(嵌入式学习,linux,shell,嵌入式)