Linux Shell脚本应用
stevezhou 2014.10.04
一部shell基础视频教程的笔记,以此备忘:
执行Shell脚本
- chmod +x uad.sh
- ./uadsh
---------------------------------
- sh uad.sh
---------------------------------
- souce uad.sh
Shell命令的组合运用
管道操作
| 前一条命令的输出作为后一条命令的输入
重定向操作 :
改变执行命令时的默认输入输出
类型 | 操作符 | 用途 |
---|---|---|
重定向输入 | < |
从指定文件读取数据,而不是从键盘输入 |
重定向输出 | > (>>) |
将输出结果覆盖(追加)到指定文件 |
标准错误输出 | 2> (2>>) |
将错误信息覆盖(追加)到指定文件 |
混合输出 | &> (&>>) |
将标准输出和错误信息覆盖(追加)到指定文件 |
命令分隔
处理两个命令间的逻辑关系
&& | 逻辑与 |
|| | 逻辑或 |
; | 顺序执行 |
使用变量
定义及赋值:变量名=变量值
引用变量:$变量名 、${变量名}
双引号:允许引用、\转义
单引号:禁止引用、转义
反撇号(1左边),或者 $() :以命令输出进行替换
由系统或脚本操控,不可直接赋值的变量
$?:前一条命令的状态值,0为正常,非0异常
$0:脚本自身的程序名
$1-$9:第1-第9个位置参数
$*:命令行的所有位置参数的内容
$#:命令行的位置参数个数
数值运算
erpr 数值1 操作符 数值2
$[数值1 操作符 数值2]
自增或自减:let 变量名++ ,let 变量名--
随机数:RANDOM 变量
生成数据序列
seq 首数 末数
seq 首数 增量 末数
小数运算:将表达式给bc命令处理
echo "40.6-20.21"|bc
echo "scale=3; 10/3"|bc
字符串子串截取操作
路径分割
dirname 路径字符串
basename 路径字符串
使用expr命令
expr substr $变量名 起始位置 截取长度 ,起始位置从1开始
使用${}表达式
${Var1: 起始位置: 截取长度} ,起始位置从0开始
字符串替换
${变量名/匹配模式/替换字符串},只替换第一个模式匹配的字符串
${变量名//匹配模式/替换字符串} ,替换变量中模式匹配的所有字符串
获取随机字符串
head -1 /dev/urandom|md5sum|cut -b 起始位置 结束位置
条件测试
格式一:test 条件表达式 条件表达式]
格式二:[ 条件表达式 ] ,注意条件表达式左右必须有空格
文件状态检测(存在及识别)
-e:目标是否存在 (Exist)
-d:是否为目录(Directory)
-f:是否为文件(File)
示例: [ -f "/etc/fstab" ]
文件权限的检测
-r:是否有读取(Read)权限
-w:是否有写入(Write)权限
-x:是否有可执行(eXcute)权限
注意:对文件所有者,均有写入权限(无论“ls -l”列出的状态如何)
示例:[ -x "/etc/fstab" ]
整数值比较
-eq:等于(Equal)
-ne:不等于(Not Equal)
-gt: 大于(Greater Than)
-lt:小于(Lesser Than)
-ge:大于或等于(Greater or Equal)
-le:小于或等于(Lesser or Equal)
示例:x=3;y=5;[ $x -eq $y ]||echo 'fault'
字符串匹配
=:两个字符串相同
!=:两个字符串不相同
单分支/双分支的if应用
单分支if语句结构
if 条件测试
then 命令序列
fi
双分支if语句结构
if 条件测试
then 命令序列1
else 命令序列2
fi
多分支if语句结构
if 条件测试1
then 命令序列1
elif 条件测试2
then 命令序列2
......
else
命令序列n
fi
注:通常会用case来处理多分支的情况
for 循环
for 变量名 in 取值列表
do
命令序列
done
case分支
case语句结构
case 变量值 in
模式1)
命令序列1
;;
模式2)
命令序列2
;;
......
*)
默认命令序列
esac
chkconfig处理
在脚本开始处设置chkconfig参数
添加为系统服务 (脚本放在/etc/init.d文件夹下)
#/bin/bash
#checkconfig:- 90 10
#description:Daemon script for sleepd Server
......
awk命令应用
对文件进行逐行处理; 基于模式匹配检查输入; 将期望的匹配结果print到屏幕;
语法模式:
awk '模式 {操作}' 文件1 文件2 ......
示例:
awk 'NR==1,NR==3 {print}' /etc/hosts #输出第1行至第3行,NR为一个内置变量,代表当前行号
常见的内置变量
NR 当前处理行的序数(行号)
FS 字段分隔,缺少为空格或Tab位
$n 当前行的第n个字段
$0 当前行的所有文本内容
示例:
awk '/2/{print $2}' file.txt #输出file.txt中包含字符'2'的行的第2个字段
awk -F. '$5=="benet"{print $0}' file.txt #输出file.txt中第5字段等于'benet'行(所有字段),以‘.'作为字段分隔符
awk 与 sed:awk仅作文件过滤; sed文本过滤虽没有awk强大,但sed除可做文件过滤外,还可对文本进行修改;
sed文件处理工具
sed (Stream Editor),基于模式匹配过滤/修改文本
语法格式:
sed '编辑指令' 文件1 文件2 ...... #输出处理后的所有文件内容
sed -n '编辑指令' 文件1 文件2 ...... #仅输出受影响的行,修改不会更改文件本身内容
sed -i '编辑指令' 文件1 文件2 ...... #输出受影响的行,修改会更改文件本身内容
编辑指令的写法,多条指令间以分号隔开:
[地址1[,地址2]]操作类型
示例:
sed -n '3p;5p' file.txt #输出file.txt中第3行与第5行
常用操作类型
p 输出/打印文本行
n 取下一行文件(跳过当前行)
d 删除
s 字符串替换
a 追加新的文本
示例:
sed -n 'p;n' file.txt #输出奇数行内容
sed -n 'n;p' file.txt #输出偶数行内容
sed -n '/w2k8/,$p' file.txt #输出file.txt中,从包含'w2k8'字符串的第一行开始,到最后一行的内容; 其中 '$'代表最后一行
sed '2,3d' file.txt #输出删除2到3行后的内容(不会真正删除文件中的内容,仅输出到屏幕上)
sed '/w2k8/d;$d' file.txt #删除包含'w2k8'字符串的行与最后一行(不会真正删除文件中的内容,仅输出到屏幕上)
sed '/ne/!d' file.txt #删除不包含'ne'字符串的行
sed '3,4s/hunter/BADBOY/g' file.txt #用'BADBOY'替换3到4行中所有'hunter'字符串,其中 'g'表示全部替换
sed 's/ter//g' file.txt #删除字符串'ter' (替换为空串)
特别地:& 代表模式匹配的字符串,
sed 's/[0-9]\+/_&/' dd.txt #dd.txt文件中,在每行数字字符串前加上字符'_'
-------------------------------------------------------------
常用的sed命令如下表所列:
命令 |
功能 |
a\ |
在当前行之后插入一行或多行 |
c\ |
用新文本替换当前行中的文本,并开始新的一轮sed命令的执行 |
d |
删除行 |
i\ |
在当前行之前插入文本 |
h |
将模式空间里的内容拷贝到暂存缓冲区并替换原来暂存缓冲区的内容 |
H |
将模式空间里的内容追加到暂存缓冲区 |
g |
将里暂存缓冲区的内容拷贝到模式空间并替换原来模式空间的内容 |
G |
将暂存缓冲区里的内容追加到模式空间 |
p |
打印模式空间的内容 |
n |
读入下一行到模式空间,并接着从下一条命令开始执行 |
q |
直接退出sed,不继续执行其后的命令 |
r |
读入指定文件的内容 |
w |
将行写入文件 |
! |
对所选行以外的行进行处理 |
s/regexp/replacement/flag |
用replacement替换模式空间由regexp匹配到的内容 |
x |
交换模式空间与暂存缓冲区的内容 |
y/source-chars/dest-chars/ |
将source-chars的字符换成对应的的dest-chars中的字符,source-chars和dest-chars中的字符个数要相同。source-chars和dest-chars中都不能有正则表达式。 |
= |
打印当前行的行号,行号是令起一行打印的 |
# |
sed脚本文件中领起注释 |
替换命令s/regexp/replacement/flag 中的flag:
flag |
功能 |
g |
进行全局替换。不使用此选项将只对该行匹配到的第一个结果进行替换 |
p |
打印模式空间中的内容(替换之后的内容) |
w filename |
将替换之后的内容写入文件filename |
-----------------------------------------------------------------------------------------------------
正则表达式知识补充:
元字符 |
功能
|
示例
|
匹配结果
|
^
|
行首定位符
|
/^supinfo/
|
匹配所有以supinfo开头的行
|
$
|
行尾定位符
|
/supinfo$/
|
匹配所有以supinfo结尾的行
|
\<
|
词首定位符
|
/\<supinfo/
|
匹配出现以supinfo为开头的词的行
|
\>
|
词尾定位符
|
/supinfo\>/
|
匹配出现以supinfo为结尾的词的行
|
.
|
匹配一个字符
|
/su…fo/
|
包含su,后面紧跟三个任意字符,然后紧跟着fo的行
|
*
|
匹配0个或多个前一字符
|
/_*supinfo/
|
supinfo前有0个或多个下划线的行
|
[]
|
匹配一组字符里的任意字符
|
/[Ss]pinfo/
|
包含Supinfo或supinfo的行
|
[x-y]
|
匹配指定范围内的字符
|
/[A-Z0-9]supinfo/
|
supinfo之前有一个A到Z或0到9的字符
|
[^ ]
|
匹配不在指定范围内的字符
|
/[^A-Z0-9]supinfo/
|
supinfo之前有一个既不是A到Z又不是0到9的字符
|
x\{m\}
x\{m,\}
x\{m, n\}
|
根据字符x出现的次数匹配:
m次;大于等于m次;大于等于m次但小于等于n次
|
/s\{2,5\}/
|
匹配有2到5个连续出现的s的行
|
\
|
转义元字符
|
/supinfo\. /
|
匹配包含supinfo,然后后面紧跟一个句点的行(没有 \ 的时候是匹配一个字符)
|
\(…\)
|
创建一个字符标签
|
/(SUPINFO):use\1NE/
|
括号中的字符被保存在标号为1的标签里,以后可以用\1来引用。标签编号从左到右依次为1,2,3……最多可以有9个标签。这个例子查找的是SUPINFO:后面跟着一个 use SUPINFONE的字符串
|