shell脚本的学习和使用
Posted 两片空白
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell脚本的学习和使用相关的知识,希望对你有一定的参考价值。
目录
shell脚本编程注意事项
前言
shell:我们知道linux并不是一个可视化的操作系统,如果直接使用起来,成本比较高。而shell是一个命令行解释器,是用户与linux之间的桥梁,用户只需要输入命令,通过shell,解释成对应linux可以识别的命令。
Linux 中的 shell 有很多种类,常用的几种:
1. Bourne Shell(/usr/bin/sh 或/bin/sh)
2. Bourne Again Shell(/bin/bash)
3. C Shell(/usr/bin/csh)
4. K Shell(/usr/bin/ksh)
5. Shell for Root(/sbin/sh)
使用最多的是bash,也是shell默认的命令行解释器。
shell脚本:shell是用C语言编写的,shell脚本则是为shell编写的脚本程序。实际上,shell脚本就是一条一条linux命令组合起来,加上一些语法,为了实现一个目的。
在linux命令行编写命令,可以说也是再编写shell脚本
shell脚本编程注意事项
- shell脚本文件的命名一般以英文小写,大写,后缀以.sh结尾
- shell编程的用'#'表示注释
- shell编程必须以 #!/bin/bash 开头
- shell脚本的变量不能以数字,特殊符号开头,可以使用下划线,但是不能是用破折号
第一个shell脚本——Hello world
建立一个.sh文件,在里面编写如下内容:
执行shell脚本有两种方式:
- 给.sh文件加上可执行的权限
chmod +x first.sh
./first.sh #执行shell脚本
- 利用bash解释,将.sh文件作为bash的参数
/bin/bash first.sh
shell脚本的变量
定义变量
定义变量,变量名不需要叫'$'符号。定义变量有两种方式。
- 直接定义
a=1
注意:以这种方式命名的变量类型默认是字符串类型。
- 使用declare命令,格式为 declare [+/-] [选项] 变量名
其中 '-' 表示给变量加上特定属性,'+' 表示取消变量的特定属性。选项有一下几种:
#!/bin/bash
a=1 #字符串类型
b=2
sum1=$a+$b
echo $sum1
declare -i x=2 #整数类型
declare -i y=3
declare -i sum2
sum2=$x+$y
echo $sum2
注意点:
- 变量名和等号之间不能有空格
- 变量命名只能使用英文字母(大写或者小写),数字和下划线,首个字母不能以数字和特殊符号开头。
- 变量名中间不能有空格
- 不能使用标点符号
- 不能使用shell关键字
使用变量
使用一个变量,需要在变量前加一个'$'符号。
#!/bin/bash
#echo "hello world!"
hello="hello world!"
echo $hello
echo $hello
如下使用''大括号是为了帮助解释器识别边界范围。如下,如果不加'',解释器会将helloworld当作一个变量。
#!/bin/bash
hello="hello "
echo "$helloworld"
只读变量
使用readonly命令可以将变量定义为只读变量,只读变量不能被修改。相当于其他编程语言的常量。
删除变量
使用unset 命令可以删除变量。变量删除后,不能再被使用。
变量类型
shell存在三种变量,系统变量,环境变量,局部(用户)变量。
- 系统变量:主要是用于对参数判断和命令返回值判断时使用,系统变量详解如下:
$0 shell本身文件名;
$n 当前脚本的第n个参数,n=1,2,…9;
$* 当前脚本的所有参数(不包括程序本身);
$# 当前脚本的参数个数(不包括程序本身);
$? 令或程序执行完后的状态,返回0表示执行成功;
$$ 程序本身的PID号。
- 环境变量:所有的程序,包括 shell 启动的程序,都能访问环境变量,有些程序需要环 境变量来保证其正常运行。必要的时候 shell 脚本也可以定义环境变量。
PATH 命令所示路径,以冒号为分割;
HOME 打印用户家目录;
SHELL 显示当前Shell类型;
USER 打印当前用户名;
ID 打印当前用户id信息;
PWD 显示当前所在路径;
TERM 打印当前终端类型;
HOSTNAME 显示当前主机名;
PS1 定义主机命令提示符的;
HISTSIZE 历史命令大小,可通过 HISTTIMEFORMAT 变量设置命令执行时间;
RANDOM 随机生成一个 0 至 32767 的整数;
HOSTNAME 主机名
- 局部变量:用户在脚本中定义的变量
shell的字符串
- 介绍
- shell脚本是用C语言写的,不难得到,字符串底层是用字符数组保存的。但是shell脚本的字符串并不是以'\\0'结尾。
- 在shell脚本中'*'和'@'是通配符。
字符串是 shell 编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好
用了),字符串可以用单引号,也可以用双引号,也可以不用引号。单引号:任何字符都会原样输出。没有转义,也不能使用变量。
双引号:可以使用转义和变量。
-
拼接字符串
- 获取字符串长度:使用'#'
- 提取子字符串
注意:shell脚本的字符串是从下标0开始的。
$string:start # 从左边start位置开始,从左到右截取剩余所有的字符串
$string:start:length # 从左边start位置开始,从左到右截取length长度的字符串
$string:0-start # 从右边start位置开始,从左到右截取剩余所有的字符串
$string:0-start:length # 从右边start位置开始,从左到右截取length长度的字符串
$string#chars # 从左开始匹配第一个chars字符串,截取其右边的字符串
$string##chars # 从左开始匹配最后一个chars字符串,截取其右边的字符串
$string%chars # 从右开始匹配第一个chars字符串,截取其左边的字符串
$string%%chars # 从右开始匹配最后一个chars字符串,截取其左边的字符串
- 查找子字符串:使用 expr命令,可以进行四则运算和字符串操作,expr index是在字符串中查找字符
shell脚本反引号(``)作用:反引号包含内的字符会被作为shell命令来进行输出,并返回结果,主要是为了获得返回结果。如果想直接执行,写到脚本中就可以了。
- 替换字符串
$string/substring/replacement # 使用$replacement, 来代替第一个匹配的$substring
$string//substring/replacement # 使用$replacement, 代替所有匹配的$substring
$string/#substring/replacement # 如果$string的前缀匹配$substring, 那么就用$replacement来代替匹配到的$substring
$string/%substring/replacement # 如果$string的后缀匹配$substring, 那么就用$replacement来代替匹配到的$substring
- 判断与默认值
$str:-DEFAULT # 如果str为空, 那么就以DEFAULT作为返回值
$str:=DEFAULT # 如果str为空, 那么就以DEFAULT作为返回值, 并将str赋值为DEFAULT
$str:+OTHER # 如果str不为空, 那么就以OTHER作为返回值
$str:?ERR_MSG # 如果str为空, 那么输出报错信息ERR_MSG并推出程序
Shell数组
bash支持一维数组,不支持多维数组,并且没有限定数组的大小。
类似于C语言,数组下标有0开始编号。获取数组元素需要通过下标。下标可以是整数或者算术表达式,其值应当大于等于0。
- 定义数组
在shell中用括号来表示数组,数组元素用空格符号分割。如下:
#!/bin/bash
arr1=(1 2 3 4 5)
#单独定义数组分量
declare -a arr2
arr2[0]=a
arr2[1]=b
arr3[5]=e
- 获取数组元素
需要使用下标的方式来访问。并且必须加上花括号。
使用"@"或者"*"可以访问数组的所有元素。
- 获取数组长度
获取数组长度的方式和获取字符串长度的方式相同。
- 数组遍历
数组遍历有三种方式:
1. 标准for循环。在bash中适用,在sh中不适用
2. for in形式
3. while循环
流程控制语句
if分支语句
- 格式
//单分子
if [ 条件表达式 ];then
语句
fi
//双分支
if [ 条件表达式 ];then
语句1
else
语句2
fi
//多分支
if [ 条件表达式 ];then
语句1
elif [ 条件表达式 ];then
语句2
elif [ 条件表达式 ];then
语句3
else
语句4
fi
- 常用逻辑判断运算符
-f 判断文件是否存在 eg: if [ -f filename ];
-d 判断目录是否存在 eg: if [ -d dir ];
-eq 等于,应用于整型比较 equal;
-ne 不等于,应用于整型比较 not equal;
-lt 小于,应用于整型比较 letter;
-gt 大于,应用于整型比较 greater;
-le 小于或等于,应用于整型比较;
-ge 大于或等于,应用于整型比较;
-a 双方都成立(and) 逻辑表达式 –a 逻辑表达式;
-o 单方成立(or) 逻辑表达式 –o 逻辑表达式;
-z 空字符串;
-x 是否具有可执行权限
|| 单方成立;
&& 双方都成立表达式。
- 例子
1. 使用单分支语句判断进程是否运行
$1: 获得传入脚本第一个参数。
$():脚本里使用,为执行括号里的命令。作用相当于反引号。
grep -v 不显示含有后面的字符串
grep -c 返回显示函数
2. 判断学生成绩等级
case选择语句
case语句主要用于对多个选择条件进行匹配输出,与if elif结构相似,通常用于脚本传递输入参数,打印输出结果和内容。
- 结构:以case ... in 开头,以esac结束。
注意:
1. 每一个模式后需要以')'反括号结尾,执行的命令后,需要以双引号结尾';;'
2. esac,每一次都会执行。
#找到对应模式,执行命令
case 模式名 in
模式1)
命令
;;
模式2)
命令
;;
#以上模式执行完后,都会执行这里的命令
esac
- 例子:使用shell脚本来启动和杀死一个进程。
首先:编写一个程序,让其进入死循环。
接下来编写shell 脚本
read 命令作用:将硬件键盘输入到对应变量中。
read -p:打印后面字符串
#!/bin/bash
read -p "please select start|stop test.c# " way
case $way in
start)
gcc test.c -o test
./test &
;;
stop)
num=`ps -axj | grep test | grep -vc grep`
echo $num
if [ $num -eq 1 ];then
testpid=`pidof test`
echo $testpid
kill -9 $testpid
rm -f test
else
echo "test proc is not run"
fi
;;
#利用通配符来做其他选择判断
*)
echo "select way error"
;;
esac
echo "shell script run success"
循环语句
标准for语句
在shell脚本中支持一种和C语言for循环写法差不多的形式。但是在bash中适用,在sh解释器中不适用。
格式:
for (( ...里面写法和C语言类似... ))
do
命令
done
for...in循环语句
在bash和sh解释器中都适用
格式:variable 表示变量,value_list 表示取值列表,in
是 Shell 中的关键字。意思就是,顺序获取到在in右边元素列表的元素,直到取完。
for variable in value_list
do
statements
done
获取元素列表的方式有下面几种方式:
- 在in右边直接给出各各值,每个值之间用空格隔开。
遍历数组,实际就是将所有数组元素中间空格隔开,放到in右边。
- 给出一个取值范围。
start..end
- 使用命令的执行结果
用到$()或者反引号``来执行命令获得结果。
seq命令,获得某个范围内的整数,并且可以设置步长。
seq 2 2 100,是从2开始,每次加2,到100结束。
while循环语句
格式:
while 判断语句
do
命令
done
例子:
- 死循环
- 打印数字
注意:shell脚本同样支持break和continue关键字,作用同C语言。
select语句
格式:
select param in list
do
语句
done
select命令是一个无限循环,所以注意需要设置好退出循环条件。 select命令中,一般需要配合case命令。
注意输入是select选项的序号。
select一般结合PS3使用, PS3会在select选项后打印PS3的值。
函数
介绍
shell脚本中支持将一组命令集或语句形成一个可用块,成为shell函数。shell函数只需要定义一次,可以重复使用,提高代码的利用率。
结构:
#语法
funcname()
命令1
命令2
...
#调用
funname
传参和使用:
传参直接在掉哦那个函数后面加上需要的参数,参数之间用空格分隔
在函数里面使用参数可以使用
- $n:获得第n个参数
- $#:获得传递参数的个数
- $@或者$*:可以一次性获得全部参数
返回值:
函数可以看作是一条命令,函数里如果使用了return关键字,可以使用$?,获取到函数执行的状态码,即return的值。
但是,状态码只有8位,最大值为255。如果超过了255,会被截断。
如果想获取到的值不截断
- shell脚本的变量(不加local的)默认是全局有效,可以在里面进行操作,外面也能得到。
- 在函数体内使用echo输出,在函数体外赋值
消除一个顾虑:
在函数体内如果使用echo,在函数体外,没有接收,会被打印。
如果在函数体外接收,不会打印。
注意点:
- shell脚本中的变量默认是全局有效,如果想定义局部变量,需要加上关键字local。
函数库
以上是关于shell脚本的学习和使用的主要内容,如果未能解决你的问题,请参考以下文章