shell脚本学习之四剑客awk

简述
awk本身就是一种编程语言,它支持条件判断、循环、数组遍历等功能。我们可以使用它来对文本进行分析和处理。与sed相比,sed是逐行处理文本内数据,awk也是,不过awk又在此基础上实现对每一行每一列的操作。专业的角度来讲awk是一个报告生成器,因为awk可以对行和列进行操作,所以在awk命令下,一个文本就像是一个表格。默认列之间的分隔符是空格,行之间分隔符是\n,可以通过-F或者-v FS:指定分割符。


命令格式

awk '{pattern + action}' {filenames}

1.基本语法参数
1.单引号‘’:为了和shell语法分开,防止混淆
2.大括号{}:用来表示一组命令
3.pattern:一个过滤器,表示匹配pattern的条件的行才可以执行action
4.pattern可以是以下任意一种
-正则表达式:使用通配符匹配
-关系表达式:使用关系运算符
-模式匹配表达式:使用运算符~或者!~匹配
5.action:处理动作,一系列命令,常见的动作为print

实例:抓取IP地址

[root@jiangpeisi ~]# ifconfig eth0 |awk  '/inet/{print $2}'
172.16.30.80

[root@jiangpeisi ~]# ifconfig eth0 | grep inet | awk '{print $2}'
172.16.30.80

[root@jiangpeisi ~]# ip addr | awk '/eth0/' | awk '/inet/{print $2}'
172.16.30.80/18

2.内置参数
FS:分隔符,默认是空格作为分隔符
OFS:输出行分隔符
NR:当前行数,从1开始
NF:当前行的字段(列)个数
$0:当前记录
$1~$n:当前记录的第n个字段

实例:输出字段个数

[root@jiangpeisi ~]# who
root     pts/1        2019-03-21 11:14 (49.70.207.182)
[root@jiangpeisi ~]# who | awk '{print NF}'
5

实例:打印奇数行的行号和第一列内容

[root@jiangpeisi ~]# awk -F: 'NR%2==0{next}{print NR,$1}' /etc/passwd
1 root
3 daemon
5 lp
7 shutdown
9 mail
11 games
13 nobody
15 systemd-network
17 polkitd
19 sshd
21 chrony
23 nscd
25 admin
27 dockerroot-latest
29 test1
31 ftpuser1
33 dhcpd
35 saslauth

3.内置函数
1.gsub(r,s):在$0中用s代替r
2.index(s,t):返回s中t的第一个位置
3.length(s):返回s的长度
4.match(s,r):s是否匹配r
5.split(s,a,fs):在fs上讲s分成序列a
6.substr(s,p):返回s从p开始的子串

实例:输出字段长度

[root@jiangpeisi ~]# who
root     pts/1        2019-03-21 11:14 (49.70.207.182)
[root@jiangpeisi ~]# who | awk '{print length($2)}'
5

4.流程控制语句
1.if(condition){}else{}
2.while(condition){}
3.for(init;condition;step){}
4.Break/contitnue
实例:比较大小

[root@jiangpeisi ~]# echo 2 3 |awk '{if($1>$2){print $1}else{print $2}}'
3

[root@jiangpeisi ~]# echo 3 2 |awk '{if($1>$2){print $1}else{print $2}}'
3

补充
使用awk可以对一个文件写一个脚本,格式:

awk 'BEGIN{ commands } pattern{ commands } END{ commands }' file 

执行顺序:
第一步: 执行BEGIN { commands } pattern 语句块中的语句,在对文件操作前执行
第二步:从文件或标准输入中读取一行,然后执行pattern{ commands }语句块。它逐行扫描文件,从第一行到最后一行重复这个过程,直到全部文件都被读取完毕。
第三步:当读至输入流末尾时,执行END { commands }语句块

实例:计算用户数量

[root@jiangpeisi ~]# awk 'BEGIN {count=0;print "[start] user count is ",count} {;;count++} END{print "[end] user count is ",count}' /etc/passwd
[start] user count is  0
[end] user count is  36

实例:计算文件夹大小

[root@jiangpeisi ~]# ls -lF /etc/ | awk 'BEGIN {sum=0}{sum+=$5}END{print "The size of this dir is",sum/1024/1024,"M"}'
The size of this dir is 1.30004 M