Linux文本分析处理工具之awk、sort、uniq、cut

背景:
最近接手一些Linux下日志分析工作,在此整理下常用的分析工具,记录其参数命令~


一、AWK 命令(重量级工具)

1. 介绍

AWK是一种优良的文本处理工具。它不仅是 Linux 中也是任何环境中现有的功能最强大的数据处理引擎之一。

AWK 提供了极其强大的功能:可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上 AWK 的确拥有自己的语言:AWK 程序设计语言, 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

AWK经过改进生成的新的版本 nawkgawk,现在默认linux系统下日常使用的是gawk,用命令可以查看正在应用的awk的来源:ll /usr/bin/awk:
这里写图片描述
(系统为 Centos 7.4)

AWK的语言基础是,只要在输入数据中有模式匹配,就执行一系列指令。该实用工具扫描文件中的每一行,查找与命令行中所给定内容相匹配的模式。如果发现匹配内容,则进行下一个编程步骤。如果找不到匹配内容,则继续处理下一行。

grepsedawk 被称为linux中的”三剑客”。其中:
grep 更适合单纯的查找或匹配文本
sed 更适合编辑匹配到的文本
awk 更适合格式化文本,对文本进行较复杂格式处理


2. 基础

语法结构:

awk '{pattern + action}' filename

其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。
pattern一般就是要表示的正则表达式,用斜杠括起来;
action部分是可以省略的,缺省情况下是输出,即{print $0},至于pattern可以理解成是表达式,通过pattern表达式的值的真假,来确定是否要进行action。比如1,最简单的awk用来实现cat的功能就是 awk ‘1’,这边1就是pattern,当然,1也可以是2,3,4,5等其他数字,但如果用字母的话,就不行,因为字母会解释成变量,变量初始值未定义,初始值为假,或者可以加个!反义。

命令形式:

awk [-F|-f|-v] 'BEGIN{} // {command1; command2} END{}' filename

[-F|-f|-v] :大参数,-F 指定分隔符,-f 调用脚本,-v 定义变量 var=value
’ ‘ : 引用代码块
BEGIN :初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符
// :匹配代码块,可以是字符串或正则表达式
{} : 命令代码块,包含一条或多条命令
:多条命令使用分号分隔
END :结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息


3. 要点及示例

注:由于awk命令较为复杂,想要将其内容全部讲完篇幅较大,在此我会将一些常用的通过示例的方式去展示~

扫描二维码关注公众号,回复: 2543851 查看本文章

一些要点:
$0 表示整个当前行
$1 每行第一个字段
-F 指定分隔符(注:awk默认一个或多个连续的空格或制表符看做一个定界符,即多个空格看做一个空格),指定分隔符有三种写法:-F “|”、-F”|“、-F|
NF 字段数量变量,即每行的字段数
NR 每行的记录号,多文件记录递增
FNR 与NR类似,不过多文件记录不递增,每个文件都从1开始
\t 制表符
\n 换行符
FS BEGIN时定义分隔符
RS 输入的记录分隔符, 默认为换行符(即文本是按一行一行输入)
~ 匹配,与==相比不是精确比较
!~ 不匹配,不精确比较
== 等于,必须全部相等,精确比较
!= 不等于,精确比较
&&  逻辑与
|| 逻辑或
+ 匹配时表示1个或1个以上
/[0-9][0-9]+/ 两个或两个以上数字
/[0-9][0-9]*/ 一个或一个以上数字
OFS 输出字段分隔符, 默认也是空格,可以改为制表符等
ORS 输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕
-F'[:#/]' 定义三个分隔符

示例:

awk '{print "a"}' /etc/passwd      //输出相同个数的a行,一行只有一个a字母
awk -F "|" '{print $1}' /etc/passwd        //以"|"为分隔符,打印分割后的第一个字段
awk -F":" '{print $1 $3}' /etc/passwd      //$1与$3相连输出,不分隔
awk -F":" '{print $1,$3}' /etc/passwd      //多了一个逗号,$1与$3使用空格分隔
awk  -F ":" '{print $1,$3,$6}' OFS="|" /etc/passwd        //输出字段1,3,6,以"|"作为分隔符
awk -F":" '{print "Username:" $1 "\t\t Uid:" $3 }' /etc/passwd       //自定义输出内容
awk -F: '{print NF}' /etc/passwd        //显示每行有多少字段
awk -F: 'NF==4 {print }' /etc/passwd        //显示只有4个字段的行
awk '{print NR,$0}' /etc/passwd        //输出每行的行号
awk -F: 'NR==5 || NR==6{print}'  /etc/passwd       //显示第5行和第6行

awk '/mysql/' /etc/passwd       //匹配包含mysql的行
awk '/mysql|oracle/' /etc/passwd        //匹配包含mysql或者oracle的行
awk '/mysql/&&/oracle/' /etc/passwd     //匹配包含mysql和oracle的行
awk '!/mysql/' /etc/passwd      //不匹配包含mysql的行

IF语句必须用在{}中,且比较内容用()扩起来:
awk -F: '{if($1~/mail/) {print $1}}'  /etc/passwd     //~模糊匹配,该字段包含mail即可

awk -F":" '$1=="mysql"{print $3}' /etc/passwd  
awk -F":" '{if($1=="mysql") print $3}' /etc/passwd     //与上面相同 
awk -F":" '$3>=100{print $3}' /etc/passwd     //大于等于

awk '$6 ~ /WAIT/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt        //输出字段6匹配WAIT的行(同时打印第一行作为行头),其中输出每行行号,字段4,5,6,并使用制表符分割字段

格式化输出:
netstat -anp|awk '{printf "%-8s %-8s %-10s\n",$1,$2,$3}' 
printf表示格式输出,%格式化输出分隔符,-8长度为8个字符,s表示字符串类型
打印每行前三个字段,指定第一个字段输出字符串类型(长度为8),第二个字段输出字符串类型(长度为8),第三个字段输出字符串类型(长度为10)

while循环:
awk 'BEGIN{i=1} {while(NF>i) print NR,NF,$i,i++}' uniq.txt     //while循环如果为true会继续执行该行,直到为false,才执行下一行

ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is:",int(sum/1024),"KB"}'         //计算/home目录下,普通文件的大小,使用KB作为单位(/^d/是正则,以d开头,!/^d/就是不以d开头的行,排除文件夹类型),int是取整的意思

高难度用法:

awk '!a[$0]++' file

这是一个非常经典的去重复项的awk语句,虽然短小,不过涉及到了不少知识点,下面一一解读:
这个需要根据awk的语法结构:awk '{pattern + action}' filename 去理解:

  1. 整个模式,没有用到action,所以采用的是默认的{print $0},即在patten为真条件来,输出行
    patten分析。
  2. 使用了一个hash数组,a,数组的键值采用$0,即每行值。
  3. a[$0]未声明时,a[$0]为假,在未声明的情况下,进行一次a[ 0 ] + + a [ 0]即为真

结论:当相同的行第一次读入时,pattern为真,行输出,再次读入后,patten为假,行乎略


二、sort 命令

介绍:
sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出。sort命令既可以从特定的文件,也可以从stdin中获取输入。

重要参数:
-b:忽略每行前面开始出的空格字符;
-c:检查文件是否已经按照顺序排序;
-d:排序时,处理英文字母、数字及空格字符外,忽略其他的字符;
-f:排序时,将小写字母视为大写字母;
-i:排序时,除了040至176之间的ASCII字符外,忽略其他的字符;
-m:将几个排序号的文件进行合并;
-M:将前面3个字母依照月份的缩写进行排序;
-n:依照数值的大小排序;默认是按字符字典排序
-k:后面接分段数,根据某一段来排序。默认分段符为空格或制表符
-o<输出文件>:将排序后的结果存入制定的文件;
-r:以相反的顺序来排序;默认是升序排列,加了-r变降序排列
-u:排序后去除重复行
-t<分隔字符>:指定排序时所用的栏位分隔字符;
+<起始栏位>-<结束栏位>:以指定的栏位来排序,范围由起始栏位到结束栏位的前一栏位。

示例:

1.sort -nrk 2 -t: sort.txt      //以":"为分隔符,对第二段按数值进行降序排序

三、uniq 命令

用来删除文件中重复的行

语法结构:

uniq [ -c | -d | -u ] [ -f Fields ] [ -s Characters ] [ -Fields ] [ +Characters ] [ InFile [ OutFile ] ]

重点介绍:

uniq 命令读取由 InFile 参数指定的标准输入或文件。

该命令首先比较相邻的行,然后除去第二行和该行的后续副本。重复的行一定相邻。(在发出 uniq 命令之前,请务必使用 sort 命令使所有重复行相邻,不然无法达到去重效果)最后,uniq 命令将最终单独的行写入标准输出或由 OutFile 参数指定的文件。

InFile 和 OutFile 参数必须指定不同的文件。如果输入文件用“- ”表示,则从标准输入读取;输入文件必须是文本文件。文本文件是包含组织在一行或多行中的字符的文件。这些行的长度不能超出 2048 个字节(包含所有换行字符),并且其中不能包含空字符。

缺省情况下,uniq 命令比较所有行。如果指定了-f Fields 或 -Fields 标志, uniq 命令忽略由 Fields 变量指定的字段数目。 field 是一个字符串,用一个或多个 <空格 > 字符将它与其它字符串分隔开。

如果指定了 -s Characters 或 -Characters 标志, uniq 命令忽略由 Characters 变量指定的字段数目。为 Fields 和 Characters 变量指定的值必须是正的十进制整数。

如果执行成功,uniq 命令退出,返回值 0。否则,命令退出返回值大于 0

主要参数:
-c :在输出行前面加上每行在输入文件中出现的次数(出现一次即为1)
-d :仅显示重复行。
-u :仅显示不重复的行。
-f :后接 Fields(数字);忽略由 Fields 变量指定的字段数目,如 -f 1 忽略第一段;如果 Fields 变量的值超过输入行中的字段数目, uniq 命令默认用空字符串(一个或多个空格、制表符)进行比较。
-s :后接 Characters(数字);忽略由 Characters 变量指定的字符的数目。如 -s 5就忽略后面5个字符。如果 Characters 变量的值超过输入行中的字符的数目, uniq 用空字符串进行比较。如果同时指定 -f 和 -s 标志, uniq 命令忽略由 -s Characters 标志指定的字符的数目,而从由 -f Fields 标志指定的字段后开始。
-i :不区分大小写
-w :对每行第N 个字符以后的内容不作对照

示例:

sort uniq.txt | uniq -c

先对文本进行排序,将重复行放在一起,再用uniq进行去重,同时指定-c打印重复行出现次数


四、cut 命令

使用说明:

cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。

如果不指定 File 参数,cut 命令将读取标准输入。必须指定 -b、-c 或 -f 标志之一

主要参数:

-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。
-c :以字符为单位进行分割。
-d :自定义分隔符,默认为制表符。
-f :与-d一起使用,指定显示哪个区域。
-n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的
范围之内,该字符将被写出;否则,该字符将被排除。

示例:

cut -f 2 -d "|" test.txt    //以"|"分隔符,截取第2段
cut -c 2 test.txt           //取第2个字符所在的这一列
cut -b 5-7 test.txt         //取第5个到第7个字节这一列(5、6、7)
cut -c 4- test.txt          //取第4个字符到之后所有字符

暂时先介绍这么多,具体日志分析中的应用在后面会结合场景和问题来深入~

猜你喜欢

转载自blog.csdn.net/Abysscarry/article/details/81084778
今日推荐