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` 反向输出

例子5 删除本地所有docker镜像

已知docker images的输出如下,对于每个image id要调用 docker rmi的命令

$ docker images
REPOSITORY                 TAG       IMAGE ID       CREATED         SIZE
apache                     test      3f4b9771aca2   22 hours ago    148MB
ubuntu                     sshd      c978c0c87cfd   23 hours ago    246MB
alpine                     gcc2      5294a9e943db   24 hours ago    223MB
alpine                     gcc       b4b874601d1e   24 hours ago    223MB
tian/test                  1.0       7bf7be2e7c57   27 hours ago    9.66MB
apache                     test      3f4b9771aca2   22 hours ago    148MB
ubuntu                     sshd      c978c0c87cfd   23 hours ago    246MB
alpine                     gcc2      5294a9e943db   24 hours ago    223MB
alpine                     gcc       b4b874601d1e   24 hours ago    223MB
tian/test                  1.0       7bf7be2e7c57   27 hours ago    9.66MB
apache                     test      3f4b9771aca2   22 hours ago    148MB
ubuntu                     sshd      c978c0c87cfd   23 hours ago    246MB
alpine                     gcc2      5294a9e943db   24 hours ago    223MB
alpine                     gcc       b4b874601d1e   24 hours ago    223MB
tian/test                  1.0       7bf7be2e7c57   27 hours ago    9.66MB
127.0.0.1:5000/echo        2.0       ea41ab66499a   47 hours ago    63.2MB 

这里需要获取第三列的数据,而且第一行的标题头不能要,写法如下: 

docker images|awk 'NR > 1 {print $3}'|awk '{print "docker rmi -f "$0}'|awk '{system($0)}'

Logo

更多推荐