设计script时,有时候需要修改脚本,例如删除或置换某些关键词。像这种在script执行过程动态修改文件的做法,称为流编辑。具有流编辑能力的工具,称为流编辑器。sed是这方面的强者。另外script执行时可能要制作报表,呈现各字段信息,awk完美解决。
一、正则表达式
正则表达式是组成“样式”的基本语法,而“样式”是运用sed和awk必备的能力。sed和awk相同的运行方式是:只要符合“样式”的数据行,就对它执行指定的“操作”。
什么是正则表达式?
正则表达式是一种描述的方法,一种小型的语言,可表示某种样式或若干种样式的组合,它的威力在于仅需几个简单的字符,便可代表许多字符串共同的样子。
1、. 代表任意字符
.a. 代表中间为a,两边随意字符的3个字符。(若要对比.本身需要用\转义)
2、^ 代表在行首
^abc abd应该出现在行首。"abc,hello"和"hello abc" 前者符合后者不符合
3、$ 代表在尾部
$abc abd应该出现在行尾。"abc,hello"和"hello abc" 后者符合前者不符合
4、[...] 字符集合
[...] 代表字符 串行中的一个字符 [aBc]代表a或B或c。[A-Z]一个大写[^A-Z]除了大写之外的一个字符。
5、*出现0个以上
a*c可以是abc、abbc、abbbc、aSJKSKBKc.....
6、\{...\}指定符合的个数
\{3,5\}前边的字符有3~5个。[a-z]\{3,5\}代表以小写字母组成的字符串,长度为3~5个
7、\(..\)把对比符合的字符串暂时保存起来
a\(..\)b要保存a、b之间的2个字符,若要提取保存的字符串,可用位置参数,\1代表第一个保存的字符串,\2代表第二个保持的字符串。
二、扩展正则表达式
RE字符 意义与范例
+ 重复1个或1个以上的前一个RE字符
egrep ‘go+d‘ file 搜寻范围是 god good goood gooood......等
? 0个或1个的前一个RE字符
egrep ‘go?d‘ file 搜寻范围 god good
| 用或(or)的方式找出字符串
egrep ‘g(la|oo)d file 搜寻范围 glad good
()+ 多个重复群组的判别
echo "AxyzxyzxyzxyzC" |egrep ‘A(xyz)C‘ 意思是A开头,C结尾,中间有一个以上的"xyz"字符串的意思
注意: !在正规表达式中不是特殊字符,如果要查包含!与<的字行时, grep ‘[!>]‘ file
[!a-z] 这样反响选择是错误的,[^a-z] 这样才是正确的。
格式化打印:printf
三、sed的用法
sed是一种非交互式的流编辑器,可动态编辑文件。sed处理的对象是文件的数据流。sed的工作模式是对比每一数据行,若符合样式,就执行特定的操作。
sed的语法:sed‘样式命令‘文件
意思是如果文件某一行符合‘样式‘,就执行指定是的sed命令,如删除(d)或取代(s)或显示(p)。
这里的‘样式‘使用一对//含括,表示寻找之意。/1,6/第一行到第6行,/a/,/b/含有a到b的行
注意:sed并不会更改原文件内容。sed的工作方式是读取文件内容,经流编辑后,把结果显示到标准输出,如想要存储sed处理结果,要自行运用转向输出讲结果存成其它文件。
sed的选项:
sed -n 使用安静模式,在一般sed模式中,所有来自STDIN的数据一般都会被列出到屏幕上,加上-n后只有经过sed处理的那才一行才会被列出来。
-e 直接在指令模式上进行sed的动作编辑
-f 直接将sed动作写在一个档案内,-f filename 则可以执行filename内的sed动作。
-r sed的动作支持延申动作表示法
-i 直接修改档案读取的内容.(直接修改原文本内容,小心操作)
动作说明: [n1[,n2]]function
n1,n2不见得会存在,一般代表 选择进行的动作的行数,举例来说,如果我的动作是需要在10到20行之间进行的,则10,20[动作行为]
function 有底下这些东西:
a: 新增, a的后面可以接字符串,而这些字符串会在新的一行出现(目前的下一行)
i :插入, i后面可以接字符串,而这些字符串会在新的一行出现(目前的上一行);
c :取代, c的后面可以接字符串,这些字符串可以取代 n1,n2 之间的行!
d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运作~
s :取代,可以直接直接进行取代的工作!通常这个 s 的动作可以搭配 正则表示法!例如 1,20s/old/new/g 就是!
sed的语法:
sed ‘s/要取代的字符/新字符/g‘ g表示全局的意思
1、删除某一段范围的数据行
sed ‘1,4d‘ file 把第1到第4行数据删除,剩下的显示出来。($代表最后一行‘1,$‘)
2、把含有样式的数据行删除
sed ‘/ab/d‘ file 把含有ab的所有行删除。 sed ‘/[0-9]\{3\}/d‘ file 把含有3为数的行删除。\{3\}表示//要寻找的3个数字的字符串 sed ‘/^$/d‘ file 删除空白行
3、把不含样式的行删除
sed ‘/ab/!d‘ 不含ab的行删除,剩下的显示出来。(或者说把涵ab的行不删除
4、把含有样式的数据行显示出来(但sed默认也显示不符合的数据行)
sed ‘/ab/p‘ 把含有ab的行显示出来,不符合的也显示出来 -n会抑制默认显示其它行 sed -n ‘/ab/p‘ 只把含ab的行显示出来。
5、取代
sed -n ‘s/ab/AB/p‘ file 把file中每一行第一个出现ab的字符串换位AB,sed -n ‘s/ab/AB/gp‘ file 把file中每行所有的ab都换为AB
sed -n ‘s/ab//p‘ file 把file中每行第一个ab删除(把ab置换成空字符串就是删除)
sed ‘s/^...//‘ file 把每一行开头的3个字符删除,如果^是$,则把每行最后3个字符删除。
6、取用符合样式的字符串
sed -n ‘s/\(ab\)/\1cd/p‘ file 把每行第一个出现ab的字符换为abcd 。可分解为sed -n ‘s/ \(ab\) / \1cd /p 其中( ) 1之前都用\来转义,依旧是//模式
7、找到符合样式的数据后,再进行取代操作
sed -n ‘/AAA/s/ab/AB/p‘ file 找到含有AAA的行后,把第一个出现的ab换成AB(如果是gp,就把每行出现的ab换成AB)
sed -n ‘/aaa/,/bbb/s/123/456/gp‘ file将含有aaa到bbb的那几行,把所有的123换成456
sed -n ‘2,4s/a/b/p‘ file 由第2行到第4行,把出现的第1个a换成b
例子:
cat /etc/passwd| sed ‘2a hello world‘
在第2行的后边加一行内容是helloworld,如果a前没有数字.就在每行后边另起一行,内容为hello world (如果前边的话用i)
cat /etc/passwd| sed ‘2i one \ two ‘
在第2行前边增加2行,内容分别为one、two ,每行之间要用 \(回车) 隔开
cat /etc/passwd | sed ‘2i 1 \
2 \
3 \
4 \
5‘
在第2行前边增加5行,内容分别是1 2 3 4 5
cat /etc/passwd | sed ‘1c hello world‘ 把第1行内容换为hello world
cat /etc/passwd | sed ‘2,4c hello world‘ 把第2-4行内容换为hello world
cat /etc/passwd | sed -n ‘1p‘ 显示第1行 如果是 sed -n ‘2,3p‘ 为显示第2行和第3行。 sed ‘$p‘显示最后一行
grep -v ‘^$‘ file | grep -v ‘^#‘ 和 egrep -v ‘^$|^#‘ regular_express.txt $代表最后一行去除空白行与行首为 # 的行列
cat /etc/passwd |sed -e ‘1d‘ -e ‘2,3c hello world‘ 把第1行删除,把第2行和第3行内容换成hello world
注意:
如果sed后跟多个选项,务必使用-e参数
四、awk的用法
awk是一种可以处理数据、产生格式化报表的语言。它的工作方式是读取数据,将每一行数据视为一条记录,每笔记录以字段分隔符分成若干字段,然后输出各个字段的值。
awk对每一条记录,都会套用一个"样式{操作}",如果该行符合样式,就执行指定的操作。
样式或操作之一可以省略。如果只有样式,表示要显示符合样式的行;如果只有操作,表示对每一行数据都执行该项操作。
awk的常用的作用格式:
awk "样式" 文件:把符合样式的数据行显示出来。
awk ‘{操作}’ 文件:对每一行都执行{}中的操作。
awk ‘样式{操作}’ 对符合样式的数据行,执行{}中的操作。
awk的几种用法:
1、awk ‘/root/‘ file
显示file中root的行
2、awk ‘{print $1,$2}‘ file ","可以省略如果让两个字符以空格隔开的话用 awk ‘{print $1 "\t" $2‘
显示file中每一行的第1个和第2个字段(默认以空格为分隔符)
3、awk ‘/ab/{print $1,$2}‘ file
显示file中有ab的行的第1个和第2个字段(以空格为分隔符)
4、awk -F: ‘/^root/{print $2,$3}‘ file
以":"为分隔符,把以root开头的行中的第2个和第3个字符显示出来。
5、awk -F: ‘BEGIN{OFS="++++"}/^root/{print $1,$2,$3}‘ /etc/passwd
把passwd中,以":"为分隔符找出首行为root的行,并显示前3个字段,并且字段之间以+++隔开
实例:
变量名称 代表意义
NF 每一行$0拥有的字段总数(默认以空格或Tab为分隔符)
NR 目前awk所处理的是第几行数据
FS 目前的分隔符,默认是空格键
[[email protected] ~]# cat 1 a2a3a4a5a b2b3b4b5b c2c3c4c5c [[email protected] ~]# cat 1|awk ‘{print $1 "\t 行:" NR "\t 该行总字段:" NF}‘ a 行:1 该行总字段:5 b 行:2 该行总字段:5 c 行:3 该行总字段:5 查阅passwd第三栏数据小于10的数据的行,并且仅列出账号和第三栏。 cat /etc/passwd|awk ‘{FS=":"}$3<10 {print $1 "\t" $3}‘ root:x:0:0:root:/root:/bin/bash bin1 daemon2 ... mail8
上边第一行会全部显示出来,这是因为我们读入第一行的时候,那些变数 $1, $2..默认还是以空格键为分隔的,所以虽然我们定义了 FS=":" 了, 但是却仅能在第二行后才开始生效。
那么怎么办呢?我们可以预先设定 awk 的变量啊! 利用 BEGIN 这个关键词!这样做:cat /etc/passwd|awk ‘BEGIN{FS=":"}$3<10 {print $1 "\t" $3}‘
显示ip地址
ifconfig |grep ‘inet addr‘|grep Bcast|awk ‘{print $2}‘|awk -F: ‘{print $2}‘
显示网络名称
cat /proc/net/dev |awk -F: ‘/eth.:|sit.:|wlan.:|ppp.:/{print $1}‘
sed与awk可以单独写出一本书,实在很强大,本篇只介绍最简单的用法。
这些都是读书笔记,接下来我们真正进入Shell实战!