linux 日志报告生成器,linux实战(一)----日志的截取-----文本过滤器grep、文本流式编辑器sed、报表生成器awk的运用...

linux实战(一)----日志的截取-----文本过滤器grep、文本流式编辑器sed、报表生成器awk的运用

2015年12月25日 16:28:50 张小凡vip 阅读数 5404更多

所属专栏: linux基础与shell编程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/q383965374/article/details/50394765

我们前面已经学习过 linux的性能查询(top),以及网络端口查询(netstat)命令等等。

怎么让我们查询到的信息按   我们需要的格式 显示生成。

就是我们本章 需要 学习练习的。

主要是grep,sed,awk3个命令的运用。

grep主要负责搜索

sed主要负责处理行

awk主要复杂处理列

我们在下一章的内容再来学习实例,如果用这几个命令来进行性能监控等。

grep

作用

grep命令可以指定文件中搜索特定的内容,并将含有这些内容的行标准输出。

grep全称是Global Regular Expression Print,表示全局正则表达式版本,它的使用权限是所有用户。

格式

grep [options]

[options]主要参数:

-c:只输出匹配行的计数。

-I:不区分大小写(只适用于单字符)。

-h:查询多文件时不显示文件名。

-l:查询多文件时只输出包含匹配字符的文件名。

-n:显示匹配行及行号。

-s:不显示不存在或无匹配文本的错误信息。

-v:显示不包含匹配文本的所有行。

pattern正则表达式主要参数:

\:忽略正则表达式中特殊字符的原有含义。

^:匹配正则表达式的开始行。

$: 匹配正则表达式的结束行。

\:到匹配正则表达式的行结束。

[ ]:单个字符,如[A]即A符合要求。

[ - ]:范围,如[A-Z],即A、B、C一直到Z都符合要求。

。:所有的单个字符。

* :有字符,长度可以为0。

....      保存已匹配的字符

正则表达式是Linux/Unix系统中非常重要的概念。正则表达式(也称为“regex”或“regexp”)是一个可以描述一类字符串的模式(Pattern)。

如果一个字符串可以用某个正则表达式来描述,我们就说这个字符和该正则表达式匹配(Match)。

这和DOS中用户可以使用通配符“*”代表任意字符类似。

在Linux系统上,正则表达式通常被用来查找文本的模式,以及对文本执行“搜索-替换”操作和其它功能。

实例

$ ls -l | grep '^a'

通过管道过滤ls -l输出的内容,只显示以a开头的行。

$ grep 'test' d*

显示所有以d开头的文件中包含test的行。

$ grep 'test' aa bb cc

显示在aa,bb,cc文件中匹配test的行。

$ grep '[a-z]\{5\}' aa

显示aa文件中所有包含每个字符串有5个连续小写字符的字符串的行。

$ grep 'w\(es\)t.*\1' aa

如果west被匹配,则es就被存储到内存中,并标记为1,然后搜索任意个字符(.*),这些字符后面紧跟着另外一个\1 ,\1也就是es,因为前面把es存储到了内存并默认标记为1了,找到就显示该行。如果用egrep或grep -E,就不用"\"号进行转义,直接写成'w(es)t.*\1'就可以了。

sed

作用

sed 常常用于一整个行的处理。sed是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

格式

sed [options] 'command' file(s)

sed [options] -f scriptfile file(s)

[options]主要参数

-n :使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。

-e :直接在命令列模式上进行 sed 的动作编辑;

-f :直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作;

-r :sed 的动作支持的是延伸型正规表示法的语法。(默认是基础正规表示法语法)

-i :直接修改读取的文件内容,而不是输出到终端。

'command'主要参数

a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~

c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!

d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚;

i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);

p :列印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~

s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!

pattern正则表达式主要参数

^    行首定位符

/^my/  匹配所有以my开头的行

$ 行尾定位符

/my$/  匹配所有以my结尾的行

. 匹配除换行符以外的单个字符

/m..y/  匹配包含字母m,后跟两个任意字符,再跟字母y的行

* 匹配零个或多个前导字符

/my*/  匹配包含字母m,后跟零个或多个y字母的行

[]   匹配指定字符组内的任一字符

/[Mm]y/  匹配包含My或my的行

[^]  匹配不在指定字符组内的任一字符

/[^Mm]y/  匹配包含y,但y之前的那个字符不是M或m的行

....      保存已匹配的字符

1,20s/youyouself/\1r/  标记元字符之间的模式,并将其保存为标签1,之后可以使用\1来引用它。最多可以定义9个标签,从左边开始编号,最左边的是第一个。此例中,对第1到第20行进行处理,you被保存为标签1,如果发现youself,则替换为your。

&      保存查找串以便在替换串中引用

s/my/**&**/  符号&代表查找串。my将被替换为**my**

\

/\

\>      词尾定位符

/my\>/  匹配包含以my结尾的单词的行

x\{m\} 连续m个x

/9\{5\}/ 匹配包含连续5个9的行

x\{m,\}      至少m个x

/9\{5,\}/  匹配包含至少连续5个9的行

x\{m,n\}     至少m个,但不超过n个

/9\{5,7\}/  匹配包含连续5到7个9的行

定址

定址用于决定对哪些行进行编辑。地址的形式可以是数字、正则表达式、或二者的结合。如果没有指定地址,sed将处理输入文件的所有行。

地址是一个数字,则表示行号;是“$"符号,则表示最后一行。

实例

删除d命令

$ sed '2d' example

删除example文件的第二行。

$ sed '2,$d' example

删除example文件的第二行到末尾所有行。

$ sed '$d' example

删除example文件的最后一行。

$ sed '/test/'d example

删除example文件所有包含test的行。

替换s命令

$ sed 's/test/mytest/g' example

在整行范围内把test替换为mytest。如果没有g标记,则只有每行第一个匹配的test被替换成mytest。

$ sed -n 's/^test/mytest/p' example

(-n)选项和p标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的test被替换成mytest,就打印它。

$ sed 's/^192.168.0.1/&localhost/' example

&;符号表示替换换字符串中被找到的部份。所有以192.168.0.1开头的行都会被替换成它自已加localhost,变成192.168.0.1localhost。

$ sed -n 's/\(love\)able/\1rs/p' example

love被标记为1,所有loveable会被替换成lovers,而且替换的行会被打印出来。

$ sed 's#10#100#g' example

不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,“#”在这里是分隔符,代替了默认的“/”分隔符。表示把所有10替换成100。

选定行的范围逗号

$ sed -n '/test/,/check/p' example

所有在模板test和check所确定的范围内的行都被打印。

$ sed -n '5,/^test/p' example

打印从第五行开始到第一个包含以test开始的行之间的所有行。

$ sed '/test/,/check/s/$/sed test/' example

对于模板test和west之间的行,每行的末尾用字符串sed test替换。

多点编辑e命令

$ sed -e '1,5d' -e 's/test/check/' example

(-e)选项允许在同一行里执行多条命令。如例子所示,第一条命令删除1至5行,第二条命令用check替换test。命令的执行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。

$ sed --expression='s/test/check/' --expression='/love/d' example

一个比-e更好的命令是--expression。它能给sed表达式赋值。

从文件读入r命令

$ sed '/test/r file' example

file里的内容被读进来,显示在与test匹配的行后面,如果匹配多行,则file的内容将显示在所有匹配行的下面。

写入文件w命令

$ sed -n '/test/w file' example

在example中所有包含test的行都被写入file里。

追加命令a命令

$ sed '/^test/a\\this is a test line' example

在example文件中'this is a test line'被追加到以test开头的行后面,sed要求命令a后面有一个反斜杠。

插入i命令

$ sed '/test/i\\new line-------------------------' example

如果test被匹配,则把反斜杠后面的文本插入到匹配行的前面。

下一个n命令

$ sed '/test/{ n; s/aa/bb/; }' example

如果test被匹配,则移动到匹配行的下一行,替换这一行的aa,变为bb,并打印该行,然后继续。

变形y命令

$ sed '1,10y/abcde/ABCDE/' example

把1--10行内所有abcde转变为大写,注意,正则表达式元字符不能使用这个命令。

退出q命令

$ sed '10q' example

打印完第10行后,退出sed。

保持和获取h命令和G命令

$ sed -e '/test/h' -e '$G example

在sed处理文件的时候,每一行都被保存在一个叫模式空间的临时缓冲区中,除非行被删除或者输出被取消,否则所有被处理的行都将打印在屏幕上。接着模式空间被清空,并存入新的一行等待处理。在这个例子里,匹配test的行被找到后,将存入模式空间,h命令将其复制并存入一个称为保持缓存区的特殊缓冲区内。第二条语句的意思是,当到达最后一行后,G命令取出保持缓冲区的行,然后把它放回模式空间中,且追加到现在已经存在于模式空间中的行的末尾。在这个例子中就是追加到最后一行。简单来说,任何包含test的行都被复制并追加到该文件的末尾。

保持和互换h命令和x命令

$ sed -e '/test/h' -e '/check/x' example

互换模式空间和保持缓冲区的内容。也就是把包含test与check的行互换。

awk

作用

awk 比较倾向于一行当中分成数个『栏位』(或者称为一个域,也就是一列)来处理。awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。

awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

格式

awk [-F  field-separator]  'commands'  input-file(s)

其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。

在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。

commands

awk的命令非常多,因为它甚至可以算是一个编程语言。我们这里就不详细讲述了。后面的实例学习中会了解到一部分常用的命令。

这里大概给出awk中的一些学习目录如下:

print和printf

awk中同时提供了print和printf两种打印输出的函数。

其中print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。

printf函数,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂。

awk的环境变量

变量描述

$n 当前记录的第n个字段,字段间由FS分隔。

$0 完整的输入记录。

ARGC 命令行参数的数目。

ARGIND 命令行中当前文件的位置(从0开始算)。

ARGV 包含命令行参数的数组。

CONVFMT 数字转换格式(默认值为%.6g)

ENVIRON 环境变量关联数组。

ERRNO 最后一个系统错误的描述。

FIELDWIDTHS 字段宽度列表(用空格键分隔)。

FILENAME 当前文件名。

FNR 同NR,但相对于当前文件。

FS 字段分隔符(默认是任何空格)。

IGNORECASE 如果为真,则进行忽略大小写的匹配。

NF 当前记录中的字段数。

NR 当前记录数。

OFMT 数字的输出格式(默认值是%.6g)。

OFS 输出字段分隔符(默认值是一个空格)。

ORS 输出记录分隔符(默认值是一个换行符)。

RLENGTH 由match函数所匹配的字符串的长度。

RS 记录分隔符(默认是一个换行符)。

RSTART 由match函数所匹配的字符串的第一个位置。

SUBSEP 数组下标分隔符(默认值是\034)。

awk运算符

运算符 描述

= += -= *= /= %= ^= **= 赋值

?: C条件表达式

|| 逻辑或

&& 逻辑与

~ ~! 匹配正则表达式和不匹配正则表达式

< <= > >= != == 关系运算符

空格 连接

+ - 加,减

* / & 乘,除与求余

+ - ! 一元加,减和逻辑非

^ *** 求幂

++ -- 增加或减少,作为前缀或后缀

$ 字段引用

in 数组成员

专属正则表达式元字符

一般通用的元字符集就不讲了,可参考我的Sed和Grep。以下几个是gawk专用的,不适合unix版本的awk。

\Y

匹配一个单词开头或者末尾的空字符串。

\B

匹配单词内的空字符串。

\<

匹配一个单词的开头的空字符串,锚定开始。

\>

匹配一个单词的末尾的空字符串,锚定末尾。

\w

匹配一个字母数字组成的单词。

\W

匹配一个非字母数字组成的单词。

\‘

匹配字符串开头的一个空字符串。

\'

匹配字符串末尾的一个空字符串。

awk编程

下面列举awk编程需要了解的东西:

变量

BEGIN模块

END模块

重定向和管道

条件语句

if语句

if/else语句,用于双重判断。

if/else else if语句,用于多重判断。

循环

数组

下标与关联数组

awk的内建函数

字符串函数

时间函数

日期和时间格式说明符

内建数学函数

自定义函数

实例

截取单列

last会列出最近登录的情况, 仅取出前五行

假设last -n 5的输出如下

[root@www ~]# last -n 5

root pts/1 192.168.1.100 Tue Feb 10 11:21 still logged in

root pts/1 192.168.1.100 Tue Feb 10 00:46 - 02:28 (01:41)

root pts/1 192.168.1.100 Mon Feb 9 11:41 - 18:30 (06:48)

dmtsai pts/1 192.168.1.100 Mon Feb 9 11:41 - 11:41 (00:00)

root tty1 Fri Sep 5 14:09 - 14:10 (00:01)

如果只是显示最近登录的5个帐号  也就是第一列

#last -n 5 | awk '{print $1}'

root

root

root

dmtsai

root

awk工作流程是这样的:读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键" 或 "[tab]键",所以$1表示登录用户,$3表示登录用户ip,以此类推。

设置分隔符

默认域分隔符是"空白键" 或 "[tab]键",如果想用其它符合作分隔符,参照下例:

/etc/passwd中是用:分割的

如下:

#cat /etc/passwd

root:x:0:0:root:/root:/bin/bash

daemon:x:2:2:daemon:/sbin:/sbin/nologin

bin:x:1:1:bin:/bin:/sbin/nologin

sys:x:80:80:desktop:/var/lib/menu/kde:/sbin/nologin

如果只是显示/etc/passwd的账户

#cat /etc/passwd |awk -F ':' '{print $1}'

root

daemon

bin

sys

-F指定域分隔符为':'。     {print $1}输出第一列

显示多行

显示/etc/passwd的账户和账户对应的shell,显示时账户与shell之间以tab键分割

#cat /etc/passwd |awk -F ':' '{print $1"\t"$7}'

root /bin/bash

daemon /bin/sh

bin /bin/sh

sys /bin/sh

-F指定域分隔符为':'。     {print $1 "\t" $7} 输出第一列  tab  和 第7列

使用BEGIN END模块

显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"。

#cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}'

name,shell

root,/bin/bash

daemon,/bin/sh

bin,/bin/sh

sys,/bin/sh

blue,/bin/nosh

awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。

正则搜索

搜索/etc/passwd里有root关键字的所有行

#awk -F ':' '/root/' /etc/passwd

root:x:0:0:root:/root:/bin/bash

这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)。

搜索支持正则,例如找root开头的: awk -F ':'  '/^root/' /etc/passwd

正则搜索显示单列

搜索/etc/passwd有root关键字的所有行,并显示对应的shell  也就是第7列

# awk -F ':' '/root/{print $7}' /etc/passwd

/bin/bash

这里指定了action{print $7}

awk环境变量的运用

我们上面提过都有哪些环境变量。

现在我们要统计/etc/passwd文件中的:文件名,每行的行号,每行的列数

使用到的变量参数如下:

FILENAME           awk浏览的文件名

NR                 已读的记录数  也就是第几行

NF                 浏览记录的域的个数  也就是 共几列

$0 输出整行

#awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd

filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash

filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh

filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh

filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh

使用printf替代print

printf就是线使用占位符占位,后面再一起传入参数,可以让代码更加简洁,易读

awk -F ':' '{printf("filename:%s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd

自定义变量

统计/etc/passwd的账户人数,每一行是一个账户,因为刚好awk是逐行遍历,所以我们自定义一个count自加就行。

当然 定义count为0需要在 awk逐行遍历之前  所以需要用BEGIN模块。

awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd

[start]user count is 0

root:x:0:0:root:/root:/bin/bash

...

[end]user count is 40

运算

我们需要统计某个文件夹下的文件占用的字节数

因为文件占用的字节数 在 ls -l命令中的第5列

所以我们使用如下命令:

ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}'

[end]size is 8657198

如果以M为单位显示:

ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}'

[end]size is 8.25889 M

注意,统计不包括文件夹的子目录。

条件语句

统计某个文件夹下不等于4096的其它文件占用的字节数-----过滤4096大小的文件:

ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}'

[end]size is 8.22339 M

数组

显示/etc/passwd的账户

awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd

0 root

1 daemon

2 bin

3 sys

4 sync

5 games

......

awk编程的内容极多,这里只罗列简单常用的用法,更多请参考 http://www.gnu.org/software/gawk/manual/gawk.html

你可能感兴趣的:(linux,日志报告生成器)