Linux下面整理数据的awk

Linux三剑客:grep,awk 和 sed,从功能上来说分别对应了查找,分段,修改。

我们这里聚焦在分类、整理、统计上。

命令含义

awk = “Aho Weiberger and Kernighan” 三个作者的姓的第一个字母,它是一种语言解析引擎。主要是过滤、分类、统计日志。

工作中常用的awk命令和含义

awk ‘BBEGIN{}END{}’ 程序开始和结束
awk ‘/Running/’ 正则匹配
awk ‘/aa/,/bb/’ 区间选择
awk ‘$2~/xxx/’ 字段匹配,这里指从第2个字段开始匹配包含xxx内容的行
awk ’NR==2’ 取第二行
awk ’NR>1’ 去掉第一行

awk的操作基于行,对于每一行又默认以空格分为多个列,行和列的分隔符可以修改。

awk的基本语法是 `awk 'pattern{action}' `,可以只有pattern或者action,只有pattern=打印pattern匹配的行们,只有action=对于每一行都执行这个action。

pattern可以有以下几种

BEGIN  执行匹配之前可以采取的action
END    执行匹配之后可以采取的action
BEGINFILE     读文件之前可以采取的action
ENDFILE       读文件之后可以采取的action
/regular expression/    匹配每行正则表达式之后可以采取的action
pattern && pattern    且
pattern || pattern    或
pattern ? pattern : pattern 三目表达式
(pattern)    
! pattern    非
pattern1, pattern2    范围表达式,对于第一个匹配pattern1到第一个匹配pattern2之间的行采取action

行操作pattern

模式 说明
NR==1 取出某一行
NR>=1 && NR>=5 取出1到5行
/oldboy/ 取出有 oldboy 的行
/101/,/105/ 取出 101-105 行
符号 > < >= <= == !=
awk ‘$2~/xxx/’ 字段匹配,这里指从第2个字段开始匹配包含xxx内容的行
awk ’NR==2’ 取第二行
awk ’NR>1’ 去掉第一行

 列操作pattern

-F 指定分隔符,指定每一列结束标记(默认是空格,连续的空格,tab键)
$数字 取出某一列,注意:在 awk 中 $ 内容一个意思,表示取出某一列
$0 整行的内容
{ptint xxx} 取列的时候使用的选项
$NF 表示最后一列

 例子1

对于所有nginx进程发送信号12

样本数据

$ ps -ef|grep /opt/nginx/ |grep -v grep
root     109775      1  0 Oct21 ?        00:16:57 ./nginx
root     109776      1  0 Oct21 ?        00:15:04 ./nginx
root     196548      1 15 Oct19 ?        1-02:08:48 ./nginx
root     196567      1 12 Oct19 ?        21:12:28 ./nginx

我们需要拿到进程号,这里对于每一行,以空格作为分隔符,进程号处于第二列,我们先输出它,然后向他发送信号-12。

$ ps -ef|grep /opt/nginx/ |grep -v grep|awk '{print $2}'|xargs kill -12 

例子2

对于上面的Nginx进程,找到以19开头的进程,发送信号50

我们要对第二列匹配以19开头的进程号,需要用到 $2 取第二列,然后用 pattern进行匹配

$ ps -ef|grep /opt/nginx/ |grep -v grep|awk '$2~/19[^ ]*/{print $2}'|xargs kill -50

附加题:对于19开头的进程进行 排序->去重->按数字的倒序显示

$ ps -ef|grep /opt/nginx/ |grep -v grep|awk '$2~/19[^ ]*/{print $2}'| sort | uniq -c | sort -nr

命令含义:

sort: 按从小到大进行排序
uniq -c :去重(相邻),还输出重复个数
-nr: 按数字进行倒叙排序
-n:按数字进行排序

 例子3

利用awk给文本中每一行加上行号

样例文本自己生成

思路:awk运行前先定义序号索引0,用来递增保存用户,将用户提取出来,按索引分别保存, 切片结束后再按行数进行循环,将数字序号与第一步保存的信息拼接打印

使用命令

cat config.h_json |awk 'BEGIN{idx=0}{m[idx]=$0;idx++;}END{for(i=0;i<NR;i++) print i+1, m[i]}

可圈可点的是这里的变量和数组都不用声明,就可以直接使用。

含义解释:

awk执行之前先idx=0

对于每一行都存入数组中,并且把idx+1

awk执行之后输出每一行和对应行号

例子4

统计域名中一级域名的出现次数

[root@shell ~]# cat url.txt 
 2 http: // www. etiantian. org/index.html
 3 http: // www. etiantian. org/1.html
 4 http: //post.etiantian. org/index.html
 5 http: //mp3.etiantian. org/index.html
 6 http: // www. etiantian.org/3.html

观察数据特征:

这里的一级域名是`www`和`post`等,他们出现的规律是`//`之后和`.`之前,按照`grep`正则表达式的方式也是可以抓出来的,但是会带着这俩特殊符号,还需要做正则表达式的提取,比较麻烦。我们这里要用awk,就需要分割列,这里的分隔符可以取`/`和`.`,然后一行就被分成了三个以上的部分: 前面 |  感兴趣的区域 | 后面balabala,然后就可以只打印出来感兴趣的区域,比较干净,然后 `sort + uniq -c` 即可

使用命令

awk -F [/.]+ '{print $2}' url.txt | sort | uniq -c

操作结果

$ awk -F [/.]+ '{print $2}' a|sort|uniq -c
      3  www
      1 mp3
      1 post

使用命令2 ( 纯 awk )

awk -F [/.]+ '{arr[$2]++}END{for(i in arr) print  i,arr[i]}' a

操作结果

$ awk -F [/.]+ '{arr[$2]++}END{for(i in arr) print  i,arr[i]}' a
mp3 1
post 1
 www 3

附加:排序 `sort -rnk2`

`-n` 字典序

`-k2` 以第二个字段作为key排序

`-r` 反向输出

猜你喜欢

转载自blog.csdn.net/qq_33882435/article/details/127530515