什么是awk
awk是一个报告生成器,格式化文本输出。在 Linux/UNIX 系统中,awk 是一个功能强大的编辑工具,逐行读取输入文本,默认以空格或tab键作为分隔符作为分隔,并按模式或者条件执行编辑命令。
awk语法
awk [选项] '命令' 文件名(推荐)
- -F “分隔符” 指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符
- -v var=value 变量赋值
命令可以由三部分组成
- BEGIN语句块
- 模式匹配的通用语句块
- END语句块
awk 常见的内置变量
1.FS
指定每行文本的字段分隔符,缺省默认为空格或制表符(tab)。与 “-F”作用相同 -v "FS=:"
awk -v FS=':' '{print $1FS$3}' /etc/passwd
#此处FS 相当于于变量 -v 变量赋值 相当于 指定: 为分隔符
2.OFS
输出时的分隔符
awk -F':' -v OFS='==' '{print $1,$3}' /etc/passwd
root==0
bin==1
daemon==2
adm==3
lp==4
3.RS
行分隔符。awk从文件上读取资料时,将根据RS的定义就把资料切割成许多条记录,而awk一次仅读入一条记录进行处理。预设值是\n
echo $PATH | awk -v RS=':' '{print $0}'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/root/bin
4.$n当前处理行的第n个字段(第n列)
5.NR当前处理的行的行号(序数)
可以取某一行
awk 'NR==1{print $0}' /etc/passwd #读取第一行
root:x:0:0:root:/root:/bin/bash
6.NF当前处理的行的字段个数
#例如取df命令显示的最后一列
df | awk '{print ($NF)}'
## 打印1到10行的内容
awk 'NR>=1 && NR<=10{print NR,$0}' /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 operator:x:11:0:operator:/root:/sbin/nologin
uid大于1000 的用户
awk -F: '$3>1000{print NR,$0}' /etc/passwd
29 nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
8.%0当前处理的行的整行内容
正则表达和动作
/regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来
line ranges:行范围
算术操作符
x+y, x-y, x*y, x/y, x^y, x%y
-x:转换为负数
+x:将字符串转换为数值
比较操作符:
==, !=, >, >=, <, <=
#####逻辑
与:&&,并且关系
或:||,或者关系
非:!,取反
模式匹配符:
~ 左边是否和右边匹配,包含关系
!~ 是否不匹配
例子
要求打印偶数行
awk -F: 'NR % 2 == 0{print $0}' /etc/passwd
解析:
NR :全部行号 除以 2 == 零的 零等于余数
条件判断
用法
awk 选项 '模式 {actions}'
条件判断写在 actions里
if语句:awk的if语句也分为单分支、双分支和多分支
单分支为if(判断条件){执行语句}
双分支为if(判断条件){执行语句}else{执行语句}
多分支为if(判断条件){执行语句}else if(判断条件){执行语句}else if(判断条件){执行语句}else if(判断条件){执行语句
for 循环
用法
for(expr1;expr2;expr3) {statement;…}
for(variable assignment;condition;iteration process) {for-body}
for(var in array) {for-body}
awk 'BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i};print sum}'
5050
计算
awk 'BEGIN{x=10;print x}' //如果不用引号awk就当作一个变量来输出了,所以不需要加$了
awk 'BEGIN{print x+1}' //不指定初始值,初始值就为0,如果是字符串,则默认为空
1
[root@localhost ~]# awk 'BEGIN{print 2.5+3.5}' //小数也可以运算
6
[root@localhost ~]# awk 'BEGIN{print 2-1}'
1
[root@localhost ~]# awk 'BEGIN{print 3*4}'
12
[root@localhost ~]# awk 'BEGIN{print 3**2}'
9
awk数组
awk数组特性:
- awk的数组是关联数组(即key/value方式的hash数据结构),索引下标可为数值(甚至是负数、小数等),也可为字符串 1. 在内部,awk数组的索引全都是字符串,即使是数值索引在使用时内部也会转换成字符串 2. awk的数组元素的顺序和元素插入时的顺序很可能是不相同的
- awk数组支持数组的数组
访问、赋值数组元素
arr[idx] = value
索引可以是整数、负数、0、小数、字符串。如果是数值索引,会按照CONVFMT变量指定的格式先转换成字符串
awk 'BEGIN{a[1]="zhangsan";print a[1]}'
数组遍历
格式
for(var in array) {for-body}
awk 'BEGIN{students[1]="zhaizong";students[2]="hezong";students[3]="haizong";for(x in students){print x":"students[x]}}'
将下标转换成 字母
a
aa 后就会不确定
案例
1.提取下面的字段中的 IP地址和时间
58.87.87.99 - - [09/Jun/2020:03:42:43 +0800] "POST /wp-cron.php?doing_wp_cron=1591645363.2316548824310302734375 HTTP/1.1" ""sendfileon
128.14.209.154 - - [09/Jun/2020:03:42:43 +0800] "GET / HTTP/1.1" ""sendfileon
64.90.40.100 - - [09/Jun/2020:03:43:11 +0800] "GET /wp-login.php HTTP/1.1"""sendfileo
使用awk对日志内容格式化输出,1和4 字段
分割 [
2.提取host.txt主机名后再放回host.txt文件 >>
1 www.kgc.com 2 mail.kgc.com 3 ftp.kgc.com 4 linux.kgc.com 5 blog.kgc.com
使用awk的示例:
awk '{print $2}' host.txt >> host.txt
这个命令假设主机名总是在第二个字段(由空白字符分隔)。