awk

今天用grep “chatmsg” ./debug.log.2018-12-10 搜索,发现用户有很多堆积消息,于是想着找出消息数太多的用户。于是awk派上用场了,以前几乎不太关注这个命令,尽管知道它的强大,但是没有实际用过。

1 查找
首先是打印相关的列

[root@localhost test1]# grep “chatmsg” ./debug.log.2018-12-10 | awk ‘{print $6,$8}’

Alt
第6列和第8列正是需要的,但是需要查找的是消息数很大的,于是需要条件查找。
2 过滤
查找消息数大于500的情况

[root@localhost test1]# grep “chatmsg” ./debug.log.2018-12-10 | awk ‘$8>500 {print $6,$8}’


这里有很多相同的用户id,于是去重。

3 去重

[root@localhost test1]# grep “chatmsg” ./debug.log.2018-12-10 | awk ‘$8>500 {print $6}’ | sort $1 | uniq

在这里插入图片描述
uniq 是对相同的行去重
sort $1 是对第一列排序

至此领略到了awk威力,下面系统了解wak。

1 初识

awk是流式处理程序,所谓流就好比tcp网络流一般,而这里的流指文件流,可以想象文件如水一般一行行流过awk,而awk通过预定义的命令对于数据流处理。
还是通过看一个最简单的例子理解awk:

$ awk ‘{print “Hello World!”}’

在终端执行这个命令,等待用户输入,不管输入什么都是输出hello world。print "Hello World!"就是一个命令,从stdin读取数据,按照一定规则输出到stdout。
这个例子太简单,并没有说明什么问题,下面再看一个例子:

$ awk ‘{print $1}’

输入hello world 输出为hello,不论输入什么句子都是输出第一个单词。看到这里awk的面纱解开了,通过预定义的命令 print $1 对输入的数据处理,命令格式是’{ 命令}’。awk从文件中一行行读取数据,一行数据也称之为一条记录,用$1, 2... 2 ... 2...n代表一条记录中的字段,下标是从1开始,因为$0代表整条记录原样输出,字段默认是用空格分开。
如:

$ echo “I start to study awk” | awk ‘{print $1,$5}’

输出:I awk

上面的例子都是awk通过管道读取数据,再看从文件读取数据。

$ cat data2.txt
One line of test text.
Two lines of test text.
Three lines of test text.

$ awk ‘{print $1}’ data2.txt
One
Two
Three

这里仅仅显示每行第一个字段。

1.1 分隔符

前面字段之间默认的都是空格分隔符,但是可以用-F指定别的分隔符。
比如/etc/passwd文件是以:作为分隔符。

$ awk -F : ‘{print $1}’ /etc/passwd

输出所有用户

1.2 使用多个命令

$ echo “I begin to start awk” | awk ‘{$5=“go”; print $0}’
I begin to start go

用go代替awk后输出整行,命令间需要;

1.3 从文件中读取命令

前面例子中命令是直接在终端输入的,也可以将命令写在文件中。

$ cat scripts0.awk
{print $1 "'s home directory is " $6}

$ awk -F : -f ./script2.gawk /etc/passwd

文件中多条命令

$ cat scripts1.awk
{
$5=“go”
print $0
}

$ echo “I begin to start awk” | awk -f scripts1.awk
I begin to start go

1.4 处理数据前后运行脚本

$ awk ‘BEGIN {print “The scripts1.awk File Contents:”} {print $0} END {print “End of File”}’ ./scripts1.awk
The scripts1.awk File Contents:
{
$5=“go”
print $0
}
End of File

通过BEGIN 和END 命令 处理数据前后执行命令。

2 进阶

2.1 变量

2.1.1 内建变量
变量描述
FS输入字段分隔符
RS输入记录分隔符
OFS输出字段分隔符
ORS输出记录分隔符
ENVIRON当前shell环境变量
NR已处理的输入记录数
FILENAME用作awk输入数据的数据文件的文件名

分隔符修改

$ awk ‘BEGIN{FS=":";OFS="\t\t" } {print $1,$6}’ /etc/passwd

脚本开始执行前设置字段分割符FS=":“和输出字段分隔符OFS=”\t\t"

$ echo “hello:world” | awk ‘BEGIN{FS=":" ;OFS="|"} {print $1,$2}’
hello|world

这个例子也是将输出分隔符设置为OFS="|"

$ cat data1

name python
age  12
addr shenzhen

name go
age  15
addr beijing

name  java
age   20
addr  shanghai

awk ‘BEGIN{FS="\n";RS=""} {print $1,$3}’ ./data1
name python addr shenzhen
name go addr beijing
name java addr shanghai

这里将每个用户基本信息作为一个字段FS="\n",用户作为一条记录RS="",以空行为分隔符。

环境变量

$ awk ‘BEGIN{print ENVIRON[“HOME”];print ENVIRON[“PATH”]}’
/root
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/scylladb/bin:/opt/scylladb/sbin:/root/bin

2.1.2 自定义变量

$ awk ‘BEGIN{test=“hello world”;print test}’
hello world

awk ‘BEGIN{x=4; x= x * 2 + 3; print x}’
11

awk都可以用于运算。

2.2 数组

一般编程语言和脚本都有数组,awk也有,简直就是脚本语言。
格式:arr[index]=val,这里数组是关联数组,index可以是整数或者字符串。

$ awk ‘BEGIN{var[1]=1;var[2]=4;total=var[1]+var[2];print total}’
5

再看遍历数组,arr.awk文件内容如下:

BEGIN{
    arr["a"]=1
    arr["b"]=2
    arr[2]=3
    for (i  in arr)
    {
        print "Index:",i," - Value:",arr[i]
    }
}

$ awk -f arr.awk
Index: a - Value: 1
Index: b - Value: 2
Index: 2 - Value: 3

2.3 结构化命令

2.3.1 if语句

$ cat data2
20
2
3
5
34

$ awk ‘{if ($1%2) print $1,“is jishu” ; else print $1,“is oushu”}’ ./data2
20 is oushu
2 is oushu
3 is jishu
5 is jishu
34 is oushu

奇偶数的判断,如果将脚本写在文件中跟c语法一样。

2.3.2 while语句
BEGIN{
    i=1
    sum=0
    while(i<10){
        sum+=i
        i++
    }
    print "sum: ",sum
}

这是脚本

$ awk -f sum.awk
sum: 45

这里如果没有BEGIN就不会执行,等待数据输入才会执行,这正是流式处理。

再看一个求平均数例子
这是数据文件data3

130 120 135
160 150 170
100 110 120

这是脚本average.awk

{
    sum=0
    i=1
    while(i<4){
        sum+=$i
        i++
    }
    print "average: ",sum/3
}

$ awk -f average.awk data3
average: 128.333
average: 160
average: 110

还有do while和for语句,和c语言一模一样。

2.4 函数

格式:function name([variables]){
statements
}

脚本func.awk对data3 每行前二个字段求和

function sum(num1,num2){
    return num1+num2
}

{
    print "sum: ",sum($1,$2)
}

$ awk -f func.awk data3
sum: 250
sum: 310
sum: 210

看到这里发现awk对数据处理太厉害了,用别的语言还真没这个方便。

2.5 模式

2.5.1 正则表达式

$ awk ‘BEGIN{FS=":"} /mysql/{print $0}’ /etc/passwd
mysql: x:27:27:MySQL Server:/var/lib/mysql:/bin/bash

过滤mysql用户,/mysql/模式需要放在{}左侧。

2.5.2 匹配操作符(~)

$ awk -F: ‘$1 ~ /mysql/{print 1 , 1, 1,NF}’ /etc/passwd
mysql /bin/bash

匹配第一个字段是mysql的记录

2.5.3 数学表达式

查看passwd哪些用户属于root组

$ awk -F: ‘$4 == 0{print $1}’ /etc/passwd
root
sync
shutdown
halt
operator

$4 == 0匹配条件

参考

  1. coolshell
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值