linux文件流编辑-sed、(g)awk

2018-07-03 11:07:43

sed和awk都可以当做脚本语言解释器使用,但是我们一般只会拿来在命令行上利用管道来处理一些简单的文件流。如果要从处理复杂的文件流,我们一般会用功能更加强大的lua、perl、python等脚本语言来处理。

sed 命令可以对文件流进行过滤和转换,一般是针对行处理。

-n	使用安静(silent)模式。
-e	直接在命令列模式上进行 sed 的动作编辑;
-f	直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作;
-r	sed 的动作支持的是延伸型正规表示法的语法。(默认是基础正规表示法语法)
-i	直接修改读取的文件内容,而不是输出到终端。

function: 
a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)
c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚
i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行)
p :列印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~ 
s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法
nl /etc/passwd | sed '2d'     #删除第二行
nl /etc/passwd | sed '3,$d'   #删除第三行到最后
nl /etc/passwd | sed '2a drink tea'   	#append 第二行
nl /etc/passwd | sed '2i drink tea'   	#insert 第二行
nl /etc/passwd | sed '2,5c  ddd'      	#替换2-5行为ddd
nl /etc/passwd | sed -n  '5,7p'       	#输出5-7行
nl /etc/passwd | sed '/root/d'        	#删除搜寻到的包含root的行
nl /etc/passwd | sed 's/login/bbb/g'   #替换
nl /etc/passwd | sed -e '3,$d' -e 's/bash/blueshell/'    #连续执行多条命令

sed -i '$a aaaaa' tmp.txt      #直接修改文件(危险)


(g)awk 一般是用来处理列的。

-F  分隔符默认为空白字符
-v var=value:自定义变量
$0  代表整行
$1  代表第一行

内置变量

#输入字段分隔符,默认为空白符
awk -v FS=':'
awk -F :

#输出字段分隔符,默认为空白符
awk -v OFS=':'

#指定输入时换行符,源换行符任有效
awk -v RS='###'

#输出时换行符
awk -v ORS='###'

#字段数量
awk -F : '{print NF}'
awk -F : '{print $(NF-1)}'

#行号
awk '{print NR}'

#文件名
awk '{print FILENAME}'

#命令行参数个数
awk '{print ARGC}'

#命令行数组
awk '{print ARGV[0]}'
[root@192 tmp]# cat /etc/passwd | awk -F ':' '{print $1"\t"$7}'
root	/bin/bash
bin	/sbin/nologin
daemon	/sbin/nologin
adm	/sbin/nologin
lp	/sbin/nologin
sync	/bin/sync
...

#显示字段数
[root@192 tmp]# awk -F : '{print NF"\t"$1}' /etc/passwd
7	root
7	bin
...
#显示行号
[root@192 tmp]# awk -F : '{print NR"\t"$1}' /etc/passwd
1	root
2	bin
3	daemon
4	adm
...
#格式化打印
[root@192 tmp]# echo -n 65 | awk '{printf("%c", $1)}'
A

简单的利用access.log来统计qps每秒并发访问量。网上很多例子利用如下命令,但是在我这里不显示任何文字,但是利用 cat 命令就可以显示,所以命令没错,只是因为管道重定向缓冲区的问题,导致不实时显示。

tail -f access.log |  awk '{print $4}' | cut -d ':' -f 4 | uniq -c

所以我改成下面的命令就有效了,fflush为刷新缓冲区。

tail -f access.log |  awk '{print $4;fflush()}' | awk -F ':' '{print $4;fflush()}' | uniq -c

注意,每个人的access.log记录的格式不一样,所以请根据自己的格式,来修改上面的命令,只要能取出当前时间的秒数(如下 53 为当前秒)就可以,我的access.log一行内容如下。

115.236.33.146 - - [03/May/2018:22:47:53 +0800] "GET http://www.ip138.com/ HTTP/1.1" 200 40281 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"


备注:
1.本系列命令都在centos7里测试,其他发行版如ubuntu、debian、fedora、opensuse等可能略微不同
2.本文只讲解常用用法,详细用法请自行利用 man 命令查看
3.原文地址http://www.freecls.com/a/2712/76

 

©著作权归作者所有
收藏
推荐阅读
简介
天降大任于斯人也,必先苦其心志。