1 Shell脚本编程注意事项
1) Shell脚本名称命名一般为英文的大写、小写
2) 不能使用特殊符号、空格来命名
3) Shell脚本后缀以.sh结尾
4) 不建议shell命名为纯数字,一般以脚本功能命名
5) Shell脚本内容首行需以#!/bin/bash开头
6) Shell脚本中变量名称尽量使用大写字母,字母间不能使用“-”,可以使用“_”
7) Shell脚本变量名称不能以数字、特殊符号开头
2 Shell变量、数组、运算、括号与引号
Shell定义变量不需要声明类型,可以使用赋值符号“=”为变量赋值;
引用变量,可以使用$变量名,例:A=123,引用:$A或${A};
如果需要明确变量的类型,可以使用declare指定类型,declare常见参数:
- +/-:“-”可用来指定变量的属性,“+”为取消变量所设置的属性
- -f:仅显示函数
- r:将变量设置为只读
- x:指定的变量会成为环境变量,可供shell以外的程序来使用
- i:指定类型为数字,字符串或运算式
2.1 shell编程中变量分为3种
系统变量、环境变量、用户变量
2.1.1 常见的系统变量
1)$0:当前脚本的名称
2)$n:当前脚本的第n个参数,n=1,2…,9
3)$*:当前脚本的所有参数(不包括程序本身),所有的参数作为一个整体
4)$@:当前脚本的所有参数(不包括程序本身),所有的参数分别作为个体
5)$#:当前脚本的参数个数(不包括程序本身)
6)$?:命令或程序执行完后的状态,返回0表示执行成功
7)$$:程序本身的PID号
2.1.2 常见的环境变量
1) PATH:命令所示路径,以冒号为分割
2) HOME:打印用户家目录
3) SHELL:显示当前shell类型
4) USER:打印当前用户名
5) ID:打印当前用户ID信息
6) PWD:显示当前所在路径
7) TERM:打印当前终端类型
8) HOSTNAME:显示当前主机名
2.1.3 用户变量
1)自定义名称
例:IP=192.168.1.1
2)read命令设置变量
read从标准输入中读取变量值,使用-p选项可以添加相应的提示
例:read -p “Please input a number:” P_NUMBER
2.2 数组
Bash提供了一维数组变量的功能,数组中的所有变量都会被编录成索引,数组的索引是以0开始的整数,且没有大小限制
2.2.1 创建数组变量
1) name[subscript]=value
例:A[0]=00 A[1]=11
2) name=(value1 value2 value3 … valuen)
例:B=(00 11 22 33 44)
2.2.2 调用数组
${name[subscript]} #subscripts是@或者*符号,将调用所有的数组成员
${#name[subscript]} #返回元素的长度;当subscript是@或者*符号,返回数组中元素的个数
2.2.3 删除数组
unset name[sbuscript]
unset name #删除整个数组
2.3 算术运算
1) 使用$((expression)),expression为算术表达式
$((x+y)) 加法;其他-、*、/、%
$((x++)) 自加1运算
$((x--)) 自减1运算
$((x**y)) 幂运算
2) 命令工具expr
expr arg1 + agr2
2.4 常见的判断逻辑运算符
1) -f:判断文件是否存在,例 if [ -f filename ]
2) -d:判断目录是否存在,例if [ -d dir ]
3) -eq:等于,应用于整型比较
4) -ne:不等于,应用于整型比较
5) -lt:小于,应用于整型比较
6) -gt:大于,应用于整型比较
7) -le:小于或等于,应用于整型比较
8) -ge:大于或等于,应用于整型比较
9) -a:双方都成立(and)
10)-o:单方成立(or)
11)-z:空字符串
12)||:单方成立
13)&&:双方都成立
2.5 判断括号区别
1) ():用于多个命令组、命令替换、初始化数组
2) (()):整数扩展、运算符、重定义变量值,算术运算比较
3) []:bash内部命令,“[”与test是等同的,正则字符范围、引用数组元素编号,不支持“+”、“-”、“*”、“/”数学运算符,逻辑测试使用-a、-o
4) [[]]:bash程序语言的关键字,不是一个命令,[[]]结构比[]结构更加通用,不支持“+”、“-”、“*”、“/”数学运算符,逻辑测试使用&&、||
5) {}:主要用于命令集合或范围,例如:mkdir –p /data/201{7,8}/ #创建2017、2018目录
{0..10} #0到10数字
{0..10..2 } #0,2,4,6,8,10数字
{2..-1} #2,1,0,-1数字
2.6 引号
2.6.1 单引号
单引号可以将它中间的所有任意字符还原为字面意义,实现屏蔽Shell元字符的功能
[root@localhost]# echo '$aa'
$aa
2.6.2 双引号
双引号类似于单引号,但不会屏蔽`、\和$这三个元字符的含义,如果需要屏蔽这些字符,须前置一个\符号,其他字符的功能将被屏蔽(包括单引号)
[root@localhost]# echo "This's"
This's
[root@localhost]# echo "$HOME"
/root
[root@localhost]# echo "\$HOME"
$HOME
2.6.3 反引号
使用反引号进行命令替换,命名替换使Shell可以将命令字符替换为命令执行结果的输出内容。也可以使用$()实现
[root@localhost]# echo `date +%D`
10/28/18
[root@localhost]# echo $(date +%D)
10/28/18
3 Shell语句语法与函数
3.1 if条件判断语句
3.1.1 if语法
if (表达式1);then
语句1
elfi (表达式2) #可省略,可有多个
语句2
else #可省略
语句3
fi
3.1.2 例子
3.2 for循环语句
for循环语句主要用于对某个数据域进行循环读取、对文件进行遍历,通常用于循环某个文件或者列表
3.2.1 for语法
for i in (表达式)
do
语句
done
3.2.2 例子
1)循环打印网址
2)循环打印1~10的数字,seq列出数据范围
3)循环求和
3.3 while循环语句
主要用于对某个数据域进行循环读取、对文件进行遍历,通常用于循环某个文件或者列表,满足循环条件会一直循环,不满足则退出循环
3.3.1 while语法
while (表达式)
do
语句
done
3.3.2 例子
1) 循环打印文件中的网址(read指令用于读取行或者读取变量)
2) 循环打印1~100(expr用于运算逻辑工具)
3.4 case选择语句
主要用于对多个选择条件进行匹配输出,通常用于脚本传递输入参数,打印出输出结果及内容
3.4.1 case语法
case 变量 in
变量1)
语句1
;;
变量2)
语句2
;;
*)
语句3
;;
Esac
3.4.2 例子
1) 输入参数并显示
运行结果:
3.5 select选择语句
一般用于选择,常用于选择菜单的创建
3.5.1 select语句
select i in (表达式)
do
语句
done
3.5.2 例子
1) 选择操作系统
运行结果:
3.6 Shell编程函数
shell函数的好处在于只需定义一次,后期随时使用,无须在shell脚本中添加重复的语句块
3.6.1 Shell函数语法
function name(){语句}
shell函数默认不能将参数传入()内部,shell函数参数传递在调用函数名称时传递
调用shell函数:
name argv1 argv2
3.6.2 例子
4 Shell编程find、sed、awk
4.1 find
主要用于操作系统文件、目录的查找
1) find语法:
find path –option [-print] [-exec -ok command] {} \;
其中option常用参数
-name filename:查找名为filename的文件
-type b/d/c/p/l/f:查找块设置、目录、字符设备、管道、符号链接、普通文件
-size n[c]:查找长度为n块[或n字节]的文件,-n则为小于n块/字节,+n为大于n块/字节
-mtime –n +n:按文件更改时间来查找文件,-n指n天以内,+n指n天以前
-atime –n +n:按文件访问时间来查找文件
-ctime –n +n:按文件创建时间来查找文件
-mmin、-amin、-cmin:已分钟来查找文件
2) 例子:
- -name
find /data/ -name “*.txt” #查找/data/目录以.txt结尾的文件
- -type
find /data/ ! –type d #查找/data/目录下的非文件夹
find /data/ -type f|xargs chmod 644 –R #查找文件类型并将权限设置为644
- -size
查找文件大于、等于、小于10M的文件
find /data/ -size +10M
find /data/ -size 10M
find /data/ -size -10M
- -mtime
find /data/ -mtime +30 -name “*.log” #查找30天以前的log
find /data/ -mtime -30 -name “*.log” #查找30天以内的log
find /data/ -mtime 30 -name “*.log” #查找第30天的log
- -exec
查找30天以前的log并删除
find /data/ -mtime +30 -name “*.log” -exec rm -rf {} \;
4.2 Sed
Sed是一个非交互式文本编辑器,可以对文本文件和标准输入进行编辑,标准输入可以来自键盘输入、文本重定向、字符串、变量和管道的文本,一次处理一行内容
在处理文本时把当前处理的行存储在临时缓冲区中,称为“模式空间”,sed命令处理缓冲区中的内容,处理完成后把缓冲区的内容输出至屏幕或者写入文件;对文件彻底修改需要加-i参数
1) Sed语法
sed [-options] [‘commands’] filename
2) sed参数与指令
- 参数
-n:静默输出,默认情况下,sed程序在所有的脚本指令执行完毕后,将自动打印模式空间中的内容,该选项可以屏蔽自动打印
-e:允许多个脚本指定被执行
-f:从文件中读取脚本指令
-i:直接修改源文件
- 指令
p:打印匹配行
a:在定位行号之后追加文本信息
i:在定位行号之前插入文本信息
d:删除定位行
s:使用替换模式替换相应模式
3) 例子
sed ‘s/old/new/g’ test.txt #test.txt文本中所有的old替换为new,g为所有匹配,没g则只替换第一次匹配
sed -n ‘1,3p’ test.txt #打印1到3行
sed ‘/old/,$d’ test.txt #删除匹配行到最后一行
sed ‘/old/anew’ test.txt #查找old行并在其下一行添加new
sed ‘www/s/^/&new’ test.txt #查找www的行并在其行首添加字符串new;&在sed表示添加
4.3 awk
awk是一个文本处理工具,原理是逐行处理文件中的数据,查找与命令行中所给定内容相匹配的模式,如果发现匹配内容,则进行下一个编程步骤,如果找不到匹配内容,则继续处理下一行
1) awk语法
awk ‘pattern + {action}’ file
2) awk参数、变量、函数与BEGIN、END
- 参数
‘’:单引号是为了和shell命令区分开
{}:大括号表示一个命令分组
patter:表示匹配patter条件的行才进行action处理
action:处理的动作,常见动作是print
patter和action可以只有其一,但不能两者都没有
- 内置变量
FS:分隔符,默认为空格
OFS:输出分隔符
NR:当前行数,从1开始
FNR:当前输入文档的当前记录编号(当前行数),尤其是当有多个输入文档时有用
NF:当前记录字段个数
$0:当前记录
$1~$n:当前记录第n个字段(列)
- 内置函数
gsub(r,s):在$0中用s代替r
index(s.t):返回s中t的第一个位置
length(s):s的长度
match(s,r):s是否匹配r
split(s,a,fs):在fs上将s分成序列a
substr(s,p):返回s从p开始的字串
- BEGIN{}是在文件开始扫描前进行的操作 ,END {}是扫描结束后进行的操作 ;一般的操作都是需要在BEGIN 设置一个初始的量
3) awk流程控制语句
- if (表达式) {语句1} else {语句2}
- while (表达式) {语句}
- do {语句} while (表达式)
- for (变量;条件;计数器) {语句}
- break:跳出循环 ; continue:终止当次循环
4) 例子
- 打印硬盘设备名称
- 以空格、\t、冒号、分号为分割
- 打印文件的3到5行;打印文件的第3行和第5行
- 打印前3行第一列
- 格式化输出passwd内容,printf打印字符串,%格式化输出分隔符,s表示字符串类型,-12表示12个字符,-6表示6个字符
- awk与if结合,判断数字比较
- 统计passwd文件用户数
awk -F ":" 'BEGIN {count=0};{name[count]=$1;count++};END{for (i=0;i