linux的Shell脚本编程

Shell脚本的建立与执行

在子Shell中执行
当执行一个脚本文件时,Shell就会产生一个子Shell(即一个子进程)去执行命令文件中的命令。
1.将文件名作为Shell命令的参数:$bash script-file
2.现将脚本文件的权限改为可执行,然后执行脚本:$script-file

在当前Shell中执行
使用source 或 “ . ”命令执行,例如:$source script-file

Shell脚本编码规范
以#!开头,指明使用何种Shell解析脚本
例如:#!/bin/bash 或 #!/usr/bin/env bash

良好的编码过饭还要求以注释说明如下的内容:
#脚本名称
#脚本功能
#作者及联系方式
#版本更新记录
#版权声明
#对算法做简要说明

Shell变量操作

变量替换

功能 表达式 说明
使用默认值 ${var:-word} 若var存在且非空,则值为$var;
若var未定义或为空值,则值为word,但var的值不变
赋予默认值 ${var:=word} 若var存在且非空,则值为$var;
若var未定义或为空值,则值为word,且var被赋值word
使用默认值 ${var:?word} 若var存在且非空,则值为$var;
若var未定义或为空值,则输出word,并终止脚本
使用默认值 ${var:+word} 若var存在且非空,则值为word;
若var未定义或为空值,则返回空值,但var的值不变

变量字符串操作

表达式 说明
${#var} 返回字符串变量var的长度
${var:m} 返回$var中从第m个字符到最后的部分
${var:m:len} 返回$var中从第m个字符开始,长度为len的部分
${var#pattern} 删除${var}中开头部分与pattern匹配的最小部分
${var##pattern} 删除${var}中开头部分与pattern匹配的最大部分
${var%pattern} 删除${var}中结尾部分与pattern匹配的最小部分
${var%%pattern} 删除${var}中结尾部分与pattern匹配的最小部分
${var/old/new} 用new替换${var}中第一次出现的old
${var//old/new} 用new替换${var}中所有的old
${var/#old/new} 用new替换${var}中开头部分的old
${var/%old/new} 用new替换${var}中结尾部分的old

变量的数值计算

运算符 说明
+、-、*、/ 四则运算
**、% 幂运算、模运算
++、– 自增、自减
=、+=、-=、*=、/=、%= 赋值运算符
<、>、<=、>=、==、!= 比较运算
&&、||、! 逻辑运算

let命令,expr命令,以及最先出现的C语言风格的Shell算术运算符((…))
例如:$((a=2+3**2-1001%5))

Shell变量的输入
read [-p ] <变量名>
让用户输入,-p指定提示语句

Shell特殊变量

位置参数 说明
$0 脚本名称
$n n是大于等于1的正数,表示n个位置的参数。当n>9时,要使用${n} 形式引用
$# 位置参数的个数
$@、“$@” 将每个位置参数看成单独字符串(以空格间隔)
$* 将所有位置参数看成一个字符串(以空格间隔)
“$*” 将所有位置参数看成一个字符串(以$IFS间隔)

Shell的进程状态变量

特殊变量 说明
$$ 当前进程的PID
$! 运行在后台的最后一个作业的PID
$? 在此之前执行的命令或脚本的返回值,0表示成功,非0表示不同原因的失败
$_ 在此之前执行的命令或脚本的最后一个参数

注意:每个命令都会返回一个退出状态码(也称为返回状态),0为成功,非0为不成功,非零值通常都被解释成一个错误码,在脚本中exit n命令将会把退出状态码(n)传递给父Shell(n必须是十进制数,范围是0~255)

Shell 脚本跟踪与调试

使用bash参数调试脚本

命令 说明
bash -n < script name> 对脚本进行语法检查,通常在执行脚本之前检查其语法是否正确
bash -v < script name> 显示脚本中每个原始命令行及其执行结果
bash -x < script name> 以调试模式执行脚本,对脚本中每条命令的处理过程:先执行替换,然后显示,再执行命令

在脚本中使用set命令调试脚本
当脚本文件较长时,可以使用set命令指定调试一段脚本。在脚本中使用set -x命令开启调试模式,使用set +x命令关闭调试模式,例如
#!/bin/bash
echo -e “Hello $LOGNAME, \c”
set -x ###开启调试模式
read -p “What is your name” name
echo “Hello $name”
set +x ###关闭调试模式

条件测试和分支结构

测试语句
格式1: test <测试表达式>
格式2: [ <测试表达式> ]
格式3: [[ <测试表达式> ]]

测试语句可以判断命令成功或失败、表达式为真或假,bash中没有布尔类型,0表示成功或真,非零表示失败或假。
注意:
1.格式1和格式2是等价的,格式3时扩展的test命令
2.在[[ ]]中可以使用Shell通配符进行模式匹配
3.&&,||,< 和>操作符能够正常的在[[ ]]中使用,但不能再[ ]中出现
4.[和[[只后的字符必须是空格,]和]]之前必须是空格
5.要读整数进行关系运算,可以使用Shell的算术运算符 (( ))进行测试

文件测试运算符

操作符 说明
-e file 文件是否存在
-f file 是否为普通文件
-d file 是否为目录
-L file 是否为符号链接文件
-b file 是否为块设备文件
-c file 是否为字符设备文件
-s file 文件长度不为0
-r file 是否为只读
-w file 是否为可写
-x file 是否为可执行
-O file 测试者是否为文件属主
-G file 测试者是否为文件同组人
-u file 是否为设置了SUID的文件
-g file 是否为设置了SGID的文件
-k file 是否为设置了黏贴位的文件
file1 -nt file2 file1是否比file2新
file1 -ot file2 file1是否比file2旧
file1 -ef file2 file1是否与file2共用相同的i-node(链接)

字符串测试操作符

操作符 说明
-z string 测试字符串是否为空串
-n string 测试字符串是否为非空串
string == string2 测试两个字符串是否相同
string != string2 测试两个字符串是否不相同

正数二元比较操作符

操作符功能 相等 不等 大于 大于等于 小于 小于等于
在[]中 -eq -ne -gt -ge -lt -le
在(( ))中 == != > >= < <=

使用逻辑操作符

操作符功能 “与”逻辑 “或逻辑” “非”逻辑
在[]中 -a -o -!
在(( ))中 && || !

分支结构循环

if语句

if < condition1>
then
	< commands1>
[ elif < condition2 >
then
	< command2 >
	..			]
[ else
	< commandn > ]
fi

注意:
1.elif语句块可以有0到多个
2.else可以为0到1个
3.条件测试可以是表达式,
4.条件测试也可以是多个命令,以最后一个命令的退出状态为其值
5.语句块可以是一条命令、多条命令,也可以是空命令“ : ”(冒号,表示该命令不做任何事,只返回一个退出状态0)
case语句

case expr in
	pattern1)
		commands1
		;;
	pattern2)
		commands2
		;;
	...
	*)
		commands
		;;
esac

注意:
1.表达式expr按顺序匹配每个模式,一旦匹配成功,则执行该模式后的命令,然后退出case
2.如果没有匹配到模式,则执行默认值“ *) ”后的命令
3.所有模式可以含有通配符和逻辑或“ | ”
4.除非特殊需要,否则每个命令块左右必须有一个双分号“ ;; ”,与C语言的switch中的break语句功能一致

while和until

while condition
do
	commands
done

当条件测试condition为真时执行循环体,否则退出循环

until  condition
do
	commands
done

当条件测试condition为真时结束循环,否则执行循环体

注意:bash提供了两个循环控制语句
break:跳出循环
continue:跳出本次循环

for语句
foreach型循环

for variable in list
do
	commands
done

先将列表list的变量依次赋给variable执行commands,
C语言型循环

for (( exp1;exp2;exp3 ))
do
	commands
done

首先执行依次exp1(只执行一次),执行exp2,为真时,执行commands,在执行exp3,进入下一次循环,为假时退出循环,

seq语句与大括号表达式

语法 举例 说明
seq n seq 10 生成序列[1…n],步长为1
seq m n seq 0 10 生成序列[m…n],步长为1
seq m s n seq 10 3 20 生成序列[m…n],步长为s
{m…n} {1…10}、{a…h}
{10…1}、{h…a}
生成序列[m…n]、[a…h],若m>n步长为1<br>生成序列[m…n]、[a…h],若m<n步长为-1
{m…n…s} {1…10…3}、{a…h…3}
{10…1…3}、{h…a…3}
生成序列[m…n]、[a…h],若m>n步长为s<br>生成序列[m…n]、[a…h],若m<n步长为-s

注意:
1.大括号表达式能生成字符序列,seq不能
2.大括号表达式能生成倒序,seq不能

select语句

select variable in list
do
	commands
done

与for的foreach类似,但是会在菜单项之前添加一个从1开始的序号依次呈现给用户,序号存在变量RELAY中。
注意:
1.list列表的菜单项间隔符由环境变量IFS决定
2.按数值顺序排列的菜单会显示到标准错误输出
3.用户直接按键将重新显示菜单
4.与for循环类似,省略in list时等价于in “$*”
5.select是个无限循环,通常要配合case语句处理不同的选单及退出。可以使用break退出循环,或exit终止脚本

函数

函数定义

[function] name() {
	commands;
}

function可以省略
注意:函数和调用它的主文件可以保持在同一个文件中,函数定义必须出现在调用之前。
函数的执行方法
name 参数1 参数2 参数n
注意:
1.调用函数时,使用位置参数的形式传递参数
2.函数内的$1-$[n]、$*和$@表示其接收的参数
3.函数调用结束后位置参数$1-$[n]、$*和$@将被重置为调用函数之前的值
4.在主程序和函数中,$0始终代表脚本名

猜你喜欢

转载自blog.csdn.net/qq_25744595/article/details/84728383