Quantcast
Channel: CodeSection,代码区,Linux操作系统:Ubuntu_Centos_Debian - CodeSec
Viewing all articles
Browse latest Browse all 11063

文本处理利器sed与awk使用总结

$
0
0

在整理为知笔记的时候,发现很久以前写的awk、sed学习笔记,这不禁然让我回想起自己最开始接触linux的情形。那时候还在江安校区东五宿舍,一天晚上打开水瞄到了一张海报――“你想了解让微软感到畏惧的操作系统么?”虽然这个讲座最后我也没听成,但也自从那时起Linux就在我心中烙下了深深的印记。上学的时候家里真的很穷,学费也是申请的助学贷款,自认自己从小开始还是比较懂事的,也不知道那时什么勇气让我跟父母开口要四千多块钱买电脑的,但父母还是爽快地支持了我,放假前入手了当时乞丐版ThinkPad R60e,这台电脑用的Celeron处理器(后面手动升级成了Core Solo单核处理器),1024x768的LCD显示器,80G的硬盘居然也装了双系统,虽然烂但是陪我度过了好几个年头,直到我研究生实习后用自己的实习工资换了另外一台联想笔记本(现在还在给我老婆用)它才下岗,当然这已是后话了!

做的这个笔记,是在放暑假前从图书馆借的那本蓝皮《Unix Shells by Example》,暑假过程中自己折腾的产物,其实当时根本不知道学习这个有什么用。sed、awk当然不会用来单独开发程序,但是在命令行处中理文本,字段切割,分析日志,以及写一些shell脚本(比如数据库patch)的时候,还是非常好用的。

一、sed - stream editor for filtering and transforming text sed的操作格式

~ sed -opts ‘command’ filename(s)

~ … | sed -opts ‘command’ # 管道输入

sed的opts选项

-n 取消默认打印。默认情况下会全文打印,因此会重复打印匹配的记录,而这个选项用来只打印匹配记录

-e 多个command可以用这个连接,比如 sed -n -e ‘cmd1’ -e ‘cmd2’ files

-i 使sed的编辑保存。默认sed操作没有破坏性(不会对原文件修改),但是确实要编辑原文件时候可以加上该参数

这里实验使用《UNIX shell by example》里面的datafile文件作为数据集。

~ cat datafile northwest NW Charles Main 3.0 .98 3 34 western WE Sharon Gray 5.3 .97 5 23 southwest SW Lewis Dalsass 2.7 .8 2 18 southern SO Suan Chin 5.1 .95 4 15 southeast SE Patricia Hemenway 4.0 .7 4 17 eastern EA TB Savage 4.4 .84 5 20 northeast NE AM Main Jr. 5.1 .94 3 13 north NO Margot Weber 4.5 .89 5 9 central CT Ann Stephens 5.7 .94 5 13 ~ 1.1 删除 d

注意,和通常的法则不一样,下面的行号都是从1开始计数的。

(a) ~ sed ‘3d’ datafile

删除第3行,其余行打印到屏幕上。再次强调sed默认没有破坏性,原文件datafile没有改变。

(b) ~ sed ‘3,$d’ datafile

删除第3行到文件的末尾记录,只打印剩余的第1,2两行。$代表文件或者记录的最后一行

(c) ~ sed ‘$d’ datafile

删除最后一行。

(d) ~ sed ‘/north/d’ datafile

删除匹配north的行,其余记录都被打印。

1.2 替换 s

标志g表示是对行内所有匹配记录都进行替换,否则只对行内首次出现的记录进行替换

(a) ~ sed -n ‘s/^west/north/p’ datafile

替换所有west打头记录,这里用了-n选项和p命令,只打印替换的记录

(b) ~ sed ‘s/[0-9][0-9]$/&.5/‘ datafile

符号$表示行末尾,符号&在替换中用于表示前面匹配的内容,上面表示行结尾为2位数的数字,添加.5成为xx.5。如果要用到&的字面意思,需要使用\&转意方可。

~ sed -n ‘s/[0-9][0-9]$/&.5\&/p’ datafile

(c) 标记符号(),可以复用前面的内容

~ sed -n 's/\(Mar\)go\(t\)/\1ianne\2/p' datafile north NO Mariannet Weber 4.5 .89 5 9 ~

这里\1复用了前面标记的Mar,而\2复用了t。

(d) 默认的替换分隔符是/,其实sed可以使用任何分隔符,就是紧跟着s的那个符号。使用自定义的符号对于操作日期、路径等特殊记录很有效

nginx pwd /home/v5kf/nginx nginx pwd | sed 's#v5kf/nginx#ztao#g' /home/ztao nginx 1.3 行范围 ,

行范围的表示是双闭合的,就是包含匹配开始的行、匹配结束的行,以及两者之间的所有行: 5,10 /Dick/,/Joe/ /north/,$

~ sed -n '/south/,/theast/s/$/**TTT**/p' datafile southwest SW Lewis Dalsass 2.7 .8 2 18**TTT** southern SO Suan Chin 5.1 .95 4 15**TTT** southeast SE Patricia Hemenway 4.0 .7 4 17**TTT** ~

这里将从south匹配行,到第一个theast匹配行结束,将每条匹配记录的$结尾替换(实际追加)成 TTT 。如果出现south,但是没有出现theast,就默认匹配到文件结尾的地方

1.4 多次编辑 -e ~ sed -e ‘1,3d’ -e ‘s/north/NORTH/‘ datafile
多个-e其操作是依次进行的,所以顺序还是有讲究的,不同的顺序对最终的结果可能会有影响 ~ sed -n -e 's/thw/THW/p' -e 's/west/WEST/p' datafile norTHWest NW Charles Main 3.0 .98 3 34 WESTern WE Sharon Gray 5.3 .97 5 23 souTHWest SW Lewis Dalsass 2.7 .8 2 18 ~ sed -n -e 's/west/WEST/p' -e 's/thw/THW/p' datafile northWEST NW Charles Main 3.0 .98 3 34 WESTern WE Sharon Gray 5.3 .97 5 23 southWEST SW Lewis Dalsass 2.7 .8 2 18 ~ 1.5 文件操作

(a) 读文件 r

将一个文件的内容加到当前的位置上实际就是在所有匹配行的下面插入文件内容

~ echo "---newfile info---" > newfile ~ sed '/west/r newfile' datafile northwest NW Charles Main 3.0 .98 3 34 ---newfile info--- western WE Sharon Gray 5.3 .97 5 23 ---newfile info--- southwest SW Lewis Dalsass 2.7 .8 2 18 ---newfile info--- southern SO Suan Chin 5.1 .95 4 15 ...

(b) 写文件 w

把所有匹配到的记录都写入到指定的文件当中

~ sed ‘/south/w newfile1’ datafile

(c) 追加文本 a

该命令是在匹配的记录后面直接追加提供的文本内容,感觉追加的内容有strip的效果,开始的空字符会被删除

~ sed ‘/south/a This is the message’ datafile

(d) 插入文本 i

跟上面的a命令类似,只不过这个i是插在匹配记录的前面

~ sed '/western/i - This is the message' datafile northwest NW Charles Main 3.0 .98 3 34 - This is the message western WE Sharon Gray 5.3 .97 5 23 southwest SW Lewis Dalsass 2.7 .8 2 18 ...

(e) 替换文本 c

用该字符替换匹配到的整个记录行

~ sed ‘/north/c This is the message’ datafile

(f) 下一行 n

对匹配到的记录,对其下一行做某些相应的操作

~ sed '/northwest/{n; s/^\<[a-z]*/XXTTZZF/; }' datafile northwest NW Charles Main 3.0 .98 3 34 XXTTZZF WE Sharon Gray 5.3 .97 5 23 southwest SW Lewis Dalsass 2.7 .8 2 18 ...

(g) 替换、转换操作 y

下面对第1,2两行记录中的字符做大写化转换

~ sed '1,2y/abcdefghigklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' datafile NORTHWEST NW CHARLES MAIN 3.0 .98 3 34 WESTERN WE SHARON GRAY 5.3 .97 5 23 southwest SW Lewis Dalsass 2.7 .8 2 18 ...

(h) 退出

直接退出,不做接下来记录的继续处理

~ sed ‘5q’ datafile
~ sed ‘/north/{ s/north/NORTH/; q; }’ datafile 1.6 sed正则表达式的元字符

Linux平台下很多工具(sed、awk、bash、python…),其正则表达式虽然在大体上约定类似,但是很多细节方面的东西还是有所差异,使用不确定最好事先查询一下!

^ 行首定位符 $ 行尾定位符 . 匹配除换行之外的单个字符 * 匹配0个或者多个前导字符(这里是前导字符0或者多个,任意一个或多个字符,使用 .* ) [] 指定字符中的任意一个字符,比如[Ll] [a-z] [^] 上面一样,不匹配的字符 \(..\) 保存匹配的字符,后面使用\1 \2..来引用,最多使用9个标签 & 保存查找匹配到的串,可以用在后面的替换中 s/love/**&**/ \< 词首定位符,单词的开头 \> 词尾定位符 x\{m\} 连续m个 x\{m,\} 至少m个 x\{m,n\} m-n个,sed -n 's/[0-9]\{2\}$/&.5/p' datafile 二、awk - pattern scanning and text processing language

注意,下面的操作都是针对gawk的。刚开始发现下面有些例程走不通,原来是Ubuntu上面默认装的个mawk,换成gawk就正常了,话说这个awk就那三个人发明的么,居然还有版本差异?

awk比上面的sed要复杂的多,支持运算符、逻辑判断、循环等基本操作,难怪在解释上面已经定位为一个language了。

awk的操作格式

~ awk -opts ‘cmd’ filenames

~ … | awk -opts ‘cmd’ # 管道输入

下面的实验操作默认使用《UNIX shell by example》里面的employees文件,也有很多是沿用上面的datafile。

~ cat employees Tom Jones 4424 5/12/66 543354 Mary Adams 5346 11/4/63 28765 Sally Chang 1654 7/22/54 650000 Billy Black 1683 9/23/44 336500 ~ 2.1 简介

awk将输入的每行作为一条记录,默认的行分隔符就是换行符。$0指代每行的整条记录,而NR将每条记录所对应的行号保存在其中。

~ awk ‘{print NR,$0}’ employees

Viewing all articles
Browse latest Browse all 11063