文本处理三剑客之awk

1.基本用法说明

文本处理,输出格式化的文本报表,执行算数运算,执行字符串操作

格式:

awk [options] 'program' var=value file...

awk [options] -f programfile var=value file...

说明:

program通常是被放在单引号中,并可以由三种部分组成

·BEGIN语句块   BEGIN{}:仅在开始处理文件中的文本之前执行一次

·模式匹配的通用语句块

·END语句块   END{}:仅在文本处理完成之后执行一次

常见选项:

-F“分隔符”指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符

-v var=value 变量赋值

 第一步:执行BEGIN{action;...}语句块中的语句

第二步:从文件或标准输入读取一行,然后执行pattern{action;...}语句块,他逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。

第三步:当读至输入流末尾时,执行END{action;...}语句块

BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化,打印输出表格的表头等语句通常可以写在BEGIN语句块中

END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块

pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{print},即打印每一个读取到的行,awk读取的每一行都会执行该语句块

 分隔符,域和记录

由分隔符分隔的字段标记$1,$2....$n称为域标识,$0为所有域;注意和shell中的变量$符含义不同

文件的每一行称为记录record

如果省略action,则默认执行print$0的操作

2.动作print

格式

print item1,item2,...

说明

逗号分隔符

输出item可以是字符串,也可以是数值;当前记录的字段,变量或awk的表达式

如省略item,相当于print$0

固定字符需要用“”引起来,而变量和数字不需要

范例

[10:09:12 root@centos7 ~]$awk '{print "hello"}'
[10:09:55 root@centos7 ~]$seq 3|awk '{print "hello"}' hello hello hello

  [10:11:35 root@centos7 ~]$seq 3|awk '{print 2*3}'
  6
  6
  6


[10:18:37 root@centos7 ~]$awk -F: '{print "yang"}' hi
wang
wang
wang
wang
wang

该文件一共有几行,就打印几个yang

[10:18:39 root@centos7 ~]$awk -F: '{print}' kao
sdad:sdasd:sdjks:sdasd:sdsd
sdsda:sdkaksd:sdkask
ssadsd
sdsd
asdasdad

打印全部内容

[10:20:50 root@centos7 ~]$awk -F: '{print $0}' kao
sdad:sdasd:sdjks:sdasd:sdsd
sdsda:sdkaksd:sdkask
ssadsd
sdsd
asdasdad

加上$0也是打印全部的意思

[10:22:45 root@centos7 ~]$awk -F: '{print $1,$3}' kao
sdad sdjks
sdsda sdkask
ssadsd
sdsd
asdasdad

以冒号为分隔符打印第一行和第三行

[10:23:52 root@centos7 ~]$awk -F: '{print $1" "$3}' kao
sdad sdjks
sdsda sdkask
ssadsd
sdsd
asdasdad

中将用tab隔开

[10:27:34 root@centos7 ~]$grep '^UUID' /etc/fstab |awk '{print $2,$3}'
/boot xfs

默认以空格做分隔符,不限制空格个数

[10:44:22 root@centos7 ~]$df | awk -F"[ %]+" '{print $5}'
Use
0
0
2
0
4
15
1
0

以空隔百分号为分隔符取出分区利用率

[10:50:28 root@centos7 ~]$df | awk -F' +|%' '/^/dev/sd/{print $1,$5}'
/dev/sda1 15

以空隔百分号为分隔符,以/dev/sd开头,取第一列和第五列

[10:58:18 root@centos7 ~]$ifconfig eth0 |awk 'NR==2{print $2}'
10.0.0.7

以空格为分割符取第二行的第二列

[11:15:16 root@centos7 ~]$ifconfig eth0 |awk '/netmask/{print $2}'
10.0.0.7

第二种方法

[11:23:22 root@centos7 ~]$cat host 
1 www.ybw.com
2 blog.yang.com
3 study.yang.com

[11:24:23 root@centos7 ~]$awk -F"[ .]" '{print $2}' host 

取出.ybw.com前面的主机名部分

3.awk变量

awk中的变量分为:内置和自定义变量

常见内置变量

范例

FS:输入字段分隔符,默认为空白字符
[11:33:37 root@centos7 ~]$awk -v FS=":" '{print $1,FS,$3}' /etc/passwd root : 0 bin : 1 daemon : 2 adm : 3 分隔符为:,引用FS

[11:39:22 root@centos7 ~]$s=:;awk -F$s '{print $1$3}' /etc/passwd
root0
bin1

设变量s=:,在awk里做为分隔符

OFS:输出字段分隔符,默认为空白字符

[11:39:30 root@centos7 ~]$awk -v FS=":" -v OFS="*" '{print $1,$3}' /etc/passwd
root*0
bin*1
daemon*2

OFS:输出字段分隔符,默认为空白字符

NF:字段数量

[11:48:28 root@centos7 ~]$awk -F: '{print NF}' /etc/passwd
7
7
7

显示这一行以冒号分割一共几个字段

[11:51:53 root@centos7 ~]$awk -F: '{print $(NF-1)}' /etc/passwd
/root
/bin
/sbin

显示倒数第二个字段

[14:17:02 root@aiyoubucuo ~]#cat nihao |awk -F"[ :]+" '{print $(NF-2)}'|tail -n +2|sort|uniq -c|sort -nr
12 123.150.181.245
1 114.246.101.61
1 100.100.30.25

取出连接数最多的三个ip

NR:记录编号

[14:19:08 root@aiyoubucuo ~]#cat nihao |awk -F"[ :]+" 'NR!=1{print $(NF-2)}'|sort|uniq -c|sort -nr
12 123.150.181.245
1 114.246.101.61
1 100.100.30.25

同上,NR!==1的意思是除去第一行都取,用来去表头

[14:22:06 root@aiyoubucuo ~]#awk '{print NR,$0}' /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

显示行号

FNR:各文件分别计数,记录的编号

[14:27:56 root@centos7 ~]$awk '{print FNR,$0}' /etc/issue /etc/redhat-release
1 S
2 Kernel on an m
3
1 CentOS Linux release 7.9.2009 (Core)
[14:28:57 root@centos7 ~]$awk '{print NR,$0}' /etc/issue /etc/redhat-release
1 S
2 Kernel on an m
3
4 CentOS Linux release 7.9.2009 (Core)

FILENAME:当前文件名

[14:37:06 root@centos7 ~]$awk '{print FNR,FILENAME,$0}' /etc/issue /etc/redhat-release
1 /etc/issue S
2 /etc/issue Kernel on an m
3 /etc/issue
1 /etc/redhat-release CentOS Linux release 7.9.2009 (Core)

4.自定义变量

自定义变量是区分字符大小写的,使用下面方式将进行赋值

-v var=value

[14:37:32 root@centos7 ~]$awk -v test1=test2="hello,gawk" 'BEGIN{print test1,test2}'
test2=hello,gawk 

5.操作符

[14:54:26 root@centos7 ~]$awk 'BEGIN{i=0;print i++,i}'
0 1
[14:54:36 root@centos7 ~]$awk 'BEGIN{i=0;print ++i,i}'
1 1
n++用法

[14:57:46 root@centos7 ~]$seq 3|awk 'n++'
2
3

n=1时++=2,所以不显示第一行。用来排除行首

[15:01:52 root@centos7 ~]$awk -F: '$3>=1000' /etc/passwd
ybw:x:1000:1000:ybw:/home/ybw:/bin/bash
yang:x:1001:1001::/home/yang:/bin/bash

操作符比较
[15:02:23 root@centos7 ~]$seq 10 |awk 'NR%2==0'
2
4
6
8
10
[15:03:34 root@centos7 ~]$seq 10 |awk 'NR%2==1'
1
3
5
7
9

取奇数,偶数行

逻辑操作符

与:&&,并且关系

或:||,或者关系

非:!,取反

[15:15:24 root@centos7 ~]$awk -F: '$3>=0 && $3<=1000 {print $1,$3}' /etc/passwd

第三列数字大于等于0,并且小于等于1000

[15:21:48 root@centos7 ~]$awk -F: '$3>=0 || $3<=1000 {print $1,$3}' /etc/passwd

从0到大于1000

[15:21:48 root@centos7 ~]$awk -F: '($3==0) {print $1,$3}' /etc/passwd

只取等于第三列等于0的行

[15:25:50 root@centos7 ~]$awk -F: '!($3==0) {print $1,$3}' /etc/passwd

取反

5.条件判断if-else

[15:49:39 root@centos7 ~]$df | awk -F' +|%' '/^/dev/sd/{if($5>=10)print $1,$5}'
/dev/sda1 15
判断以/dev/sd开头行的第5列是否大约10,如果大于则输出$1,$5

6.循环for

[16:13:31 root@centos7 ~]$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i};print sum}'
5050

7数组

[16:54:36 root@centos7 ~]$ss -nta |awk 'NR!=1{state[$1]++}END{for (i in state){print i,state[i]}}'
LISTEN 5
ESTAB 1
第一列不同的为i,state【i】为这种状态出现的次数
原文地址:https://www.cnblogs.com/aiyoubucuo/p/14243115.html