• 正文
  • 相关推荐
申请入驻 产业图谱

Linux基础-shell脚本编程

02/02 11:45
876
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

一、变量

1. shell脚本基础知识

编译型语言:如 c语言
解释型语言:shell 脚本

shell脚本的本质:shell命令的有序集合。

2.shell 编程的基本过程

基本过程分为三步:

    建立shell文件:包含任意多行操作系统命令或shell命令的文本文件。——xx.sh赋予shell文件执行权限,==用chmod命令修改权限==。执行shell文件,直接在命令行上调用shell程序

示例:

    建立shell文件 ?prog1.sh
data
    赋予shell文件执行权限 (初始文本文件无执行权限)
chmod?740?prog1.sh
#或者
chmod?u+x?prog1.sh
    执行shell文件
prog1.sh
#结果为
prog1.sh :not?found

原因是:shell在标准搜索路径中找不到prog1.sh
4.正确的执行shell文件

./prog1.sh
#结果为
2009年?12月?16日?星期二?14:52:57?CST

3. shell变量

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

    • count = 1echo $ countDATE =

data

    echo $ ?DATE

在这里插入图片描述

==注意几点:==

变量没有类型

=号两边不能加空格

变量必须是大写

赋值的时候要用``框起来

Bourne shell有如下四种变量:

用户自定义变量:

      1. 在shell编程中通常使用全大写变量:COUNT=1变量的调用,在变量前加$:echo $HOMELinux shell / bash 从右向左赋值:Y=y、X=$Y、echo $X 、y使用unset命令删除变量的赋值:Z=hello、echo $Z、hello、unset Z、echo$Z

位置变量及命令行参数:

    1. $0 与键入的命令行一样,包含脚本文件名$1,$2....$9 分别包含第一个到第九个命令行参数。$# 包含命令行参数的个数$@ 包含所有命令行参数:$1,$2,...$9$?包含前一个命令的退出状态$* ? ?包含所有命令行参数:$1,$2,....$9$$ 包含正在执行进程的ID号

    预定义变量

必须在两位数边写上 { } ,才能正常值一一样。

    环境变量

    1. HOME:/etc/passwd文件中列出的用户目录IFS: Internal Field Separator , 默认为空格,tab及换行符PATH:shell搜索路径PS1,PS2:默认提示符($)及换行提示符(>)TERM:终端类型,常用的有vt100,ansi,vt200,xterm等。

二、shell 功能语句

shell 程序由零或多条shell语句构成。shell语句包括三类:说明性语句,功能性语句和结构性语句。

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

#!/bin/sh
#
#?本程序说明
#
command_1
command_2?????#command_2的语句说明
....

常用功能性语句(命令)

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

read?var

把读入的数据全部赋给var

read?var1?var2?var3

把读入行中的第一个单词(word)赋给var1 ,第二个单词赋给var2,.....把其余所有的词赋给最后一个变量。如果执行read语句时标准输入无数据,则程序在此停留等候,直到数据的到来或被终止运行。

#!/bin/bash
echo?"input?a?number:"
read?NUM
echo?$NUM

在这里插入图片描述

#!/bin/bash
echo?"input?year?month?day:"
read?Y?M?D
echo?"Today?is?$Y-$M-$D"

==expr命令:==算术运算命令expr主要用于进行简单的整数运算,包括加(+)、减(-)、乘(*)和求模(%)等操作。例如

$expr?12?+?5?*?3
27
$expr?3?-?8?/?2
-1
$num=9
$sum=`expr?$num?*?6`
$echo?$sum
54

!!运算符间用空格分开!!

测试语句

==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是否相等
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

A="how"
B="hoW"
test?$A?=?$B
echo?$????//表示输出前一个语句的结果

在这里插入图片描述

#!/bin/bash

A="how"
B="how"
test?$A?=?$B
echo?$????//表示输出前一个语句的结果

相等为0(真),不等为1(假)

#!/bin/bash

A="how"
B="hoW"
test?$A?=?$B
echo?$????//表示输出前一个语句的结果

pwd
echo?$?

ls?file
echo?$?

最后ls file 没有,所以结果为2

#!/bin/bash

A=99
B=88
test?$A?-ne??$B
echo?$????//表示输出前一个语句的结果

test?$A?-gt??$B
echo?$????//表示输出前一个语句的结果

三、shell 分支语句

1. 条件语句

==if ..then...fi==语法结构:

if???表达式
??????????????then??命令表
fi???
    如果表达式为真,则执行命令表种的命令;否则退出if语句,即执行fi后面的语句if和fi是条件语句的语句括号,必须成对使用;命令表中的命令可以是一条,也可以是若干条。
#!/bin/bash

if?[?$#?-ne?1?]
then???
???????echo?"usage?:?$0?filename"
???????exit
fi
if?!?[?-e??$1?]
then?
????????echo?"?$1?not?exist"
????????exit
fi?
if?[?-d?$1?]
then
?????????echo?"$1?is?a?dirextory"
fi

if...then ..else..fi
语句结构为:

if????表达式
then???命令表1
else????命令表2
fi

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

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

#!/bin/bash

if?[?$#?-ne?1?]
then???
???????echo?"usage?:?$0?filename"
???????exit
fi
if?!?[?-e??$1?]
then?
????????echo?"?$1?not?exist"
????????exit
fi?
if?[?-L?$1?]
then
?????????echo?"l"
elif?[?-d?$1?]
then
?????????echo?"-"
elif?[?-b?$1?]
then?
?????????echo?"b"
else
?????????echo?"csp"
fi

在这里插入图片描述

2. 多路分支语句

==case...esac==多路分支语句case用于多重条件测试,语法结构清晰自然,

case??字符串变量???in???//case语句只能检测字符串变量
??????模式1)
???????????????命令表1??//各模拟中可用文件名元字符,以右括号结束
???????????????;;
??????模式2?|?模式3)
???????????????命令表2
???????????????;;????//命令表以单独的双分号行结束,退出case语句
.....
模式n)
????????????????命令表n
????????????????;;?????//模式n常写为字符*,表示所有其他模式
esac????????????????????//最后一个双分号行可以省略

判断选择——多路分支语句 示例1:

#!/bin/bash

echo?-n?"please choose (yes | no)?"
read?R
case?$R?in
????????yes?|?Yes?|y?|?Y?|YES?)
?????????????echo??"yes"
?????????????;;?
?????????no)
?????????????echo??"no"
?????????????;;
?????????*)
?????????????echo???"wrong"
?????????????#;;
esac

判断成绩——多路分支语句 示例2:

#!/bin/bash

echo?-n?"please choose (yes | no)?"
read?S
if?[?$S?-lt?0?-o?$S?-gt?100]
then?
????????echo?"no?in?[0-100]"
????????exit??????
fi

G=`expr?$S?/?10`
case?$G?in
????????9|10)
?????????????echo??"$S?A"
?????????????;;?
?????????6|7|8)
?????????????echo??"$S?B"
?????????????;;
?????????*)
?????????????echo???"$S?C"
?????????????#;;
esac

在这里插入图片描述

四、shell 循环语句

1. 循环语句for的用法

当循环次数已经知道或确定时候,使用for循环语句来多次执行一条或者一组命令,循环体由语句括号do和done来限定。

格式为:

for????变量名????in???单词表
?????????do??
?????????????????????命令表
??????????done

变量依次取单词表中的各个单词,每取一次单词,就执行一次循环体中的命令。循环次数由单词数确定。命令表中的命令可以是一条,也可以是由分号或换行符分开的多条。如果单词表是命令行上的所有位置参数时,可以在for

实例代码:

#!/bin/bash

#for?I??in?`ls?/etc`
do??
???????echo?"$I"
done

在这里插入图片描述

==seq命令== ?:列出一系列的数字seq ? 起始数字 ? 中间分量 ? 终止分量

#!/bin/bash
for?I?in?`seq?1?2?10`
do
??????echo?"$I"
done

示例:拷贝当前目录下的所有文件到backup子目录下。使用语法为:./prog5.sh[filename]

#The?statement?of?for?....do...done
if?[!?-d?$HOME/backup?]
then
????????mkdir?$HOME/backup
fi
flist=`ls`
for?file?in?$flist???//flist的值是ls的执行结果即当前目录下的文件名
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******???????????

2. 循环语句while的用法

语法结构:

while????命令或表达式
??????????do
???????????????命令表
??????????done

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

示例:

#!/bin/bash

I=0

while?[?$I?-lt?5?]???//-lt??=??<
do
??????I=`expr?$I?+?1`
??????echo?-n?"input?score:"
??????read?$S

??????case?`expr?$S?/?10`?in
?????????9|10)
??????????????echo?"A"
??????????????;;
????????6|7|8)
??????????????echo?"B"
??????????????;;
????????*)
??????????????echo?"C"
??????????????;;
????esac
????echo?"$I"
done

3. 循环控制语句

==break 和 continue==

break ?n 则跳出n层;continue语句则马上转到最近的一层循环语句的下一轮循环上,
continue n 则转到最近n层循环语句的下一轮循环上。

用法:prog7 整数 整数 整数 ...
参数个数不确定,范围为1-10个 ,每个参数都是正整数。

示例:

#!/bin/bash

if?[?$#?-ne?5?]
then?
??????echo?"argument?5"
??????exit
fi

for?I
do
????if?[?`expr?$I?%?2`?-eq?1?]
????then
?????????echo?"$I"
?????????else
????????????????break
????fi
done????????

若是break 的话 ,跳出整个循环。遇到偶数就跳出循环。

#!/bin/bash

if?[?$#?-ne?5?]
then?
??????echo?"argument?5"
??????exit
fi

for?I
do
????if?[?`expr?$I?%?2`?-eq?1?]
????then
?????????echo?"$I"
?????????else
????????????????continue
????fi
done????????

若是continue的话 ,跳出当前循环。遇到偶数就跳出当前循环,继续执行下面语句

五、shell 函数

1. shell函数调用

函数调用格式:

方式1:
value_name=`function_name??[arg1?arg2?...]`

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

方式2:
function_name?[arg1?arg2?...]
echo?$?

获取函数的返回状态

获取函数的返回状态 ——示例:

grep_user()
{
???R=`grep?"$1"?/etc/passwd?|?wc?-l`
???echo?$R
???return?$R
}

echo?-n?"input?username:"
read?USER
grep_user?$USER
RET=$?
if?[?$USER?-eq?1?]
then???
???????echo?"$USER?exist"
else
???????echo?"$USER?not?exist"
fi

若改为不返回值,用变量,函数的所有标准输出都传递给了主程序的变量

grep_user()
{
???R=`grep?"$1"?/etc/passwd?|?wc?-l`
???echo?$R
}

echo?-n?"input?username:"
read?USER
RET=`grep_user?$USER`
echo?"----return?$RET-----"
if?[?$USER?-eq?1?]
then???
???????echo?"$USER?exist"
else
???????echo?"$USER?not?exist"
fi

在这里插入图片描述

2. 函数变量作用域

    • 全局作用域:在脚本的其他任何地方都能够访问该变量局部作用域:只能在声明变量的作用域内访问声明局部变量的格式:

c Local variable_name = value

grep_user()
{
??????B=200
??????A=100
}

grep_user
echo?"end:?$A-$B"

结果发现函数内的变量,竟然是全局变量

如果我们要局部变量就 加一个local

grep_user()
{
??????B=200
??????local?A=100
}

grep_user
echo?"end:?$A-$B"

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

公众号『一口Linux』号主彭老师,拥有15年嵌入式开发经验和培训经验。曾任职ZTE,某研究所,华清远见教学总监。拥有多篇网络协议相关专利和软件著作。精通计算机网络、Linux系统编程、ARM、Linux驱动、龙芯、物联网。原创内容基本从实际项目出发,保持原理+实践风格,适合Linux驱动新手入门和技术进阶。