linux文本三剑客之awk编辑器

前言

我们将/etc/passwd/文件拷贝到/data/下做实验,以免影响系统

一、应用场景

过滤、统计、计算、过滤统计日志

二、awk执行

2.1工作原理

1.逐行读取文本,默认以空格或tab键为分隔符进行分割,将分割所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令;

2.sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个"字段"在进行处理

3.awk信息读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示

4.在使用awk命令的过程中,可以使用逻辑操作符“&&”表示与、“||”表示或、”!“表示非,还可以进行简单的数字运算如±*/%^,分别表示加减乘除取余和乘方

2.2命令格式

awk 选项 ‘模式或条件{操作}’ 文件1 文件按2
awk -f 脚本文件 文件1 文件2......

2.3行与列

名词 awk中的叫法 一些说明
记录record 每一行默认通过回车分割的
字段,域field 每一列默认通过空格分隔的

注意:awk中默认的东西都是可以修改的

2.3.1取行
awk
NR==1 取出某一行
NR>=1&&NR<=5 取出1-5行范围
$0 整行
/old/ 过滤
/100/,/110/ 100到110行
符号 <> >= <= == !=
[root@test1 data]# awk 'NR==1' user.txt 
1,zhangsan #取第一行
[root@test1 data]# awk 'NR>=1 && NR<=3' user.txt 
1,zhangsan #取一到三行 中间空格可加可不加
2,lisi
3,wangwu
[root@test1 data]# ll |awk 'NR==2'
-rw-r--r-- 1 root root   29 12月  3 18:24 config
[root@test1 data]# ll |awk 'NR==2{print $0}'
-rw-r--r-- 1 root root   29 12月  3 18:24 config
#两种写法的效果一样
2.3.2取列
-F 指定分隔符,指定每一列结束标记(默认是空格,连续的空格,tab键)
$ 数字 列出某一列;注意:在awk 中$内容就一个意思,表示取出某一列
column -t 文本对齐
$NF 表示最后一列
[root@test1 data]# ll |awk '{print $5}'
#必须要加花括号$加数字,就是取那一列
29
31
1306
1306
47
[root@test1 data]# ll |awk '{print $5,$9}'
#取出查看文件的大小和文件名,但是有点乱
29 config
31 ip.txt
1306 passwd
1306 test
47 user.txt
[root@test1 data]# ll |awk '{print $5,$9}' |column -t
#使用管道传给column -t对齐显示
29    config
31    ip.txt
1306  passwd
1306  test
47    user.txt
[root@test1 data]# ll |awk '{print $5,$NF}' | column -t
$NF表示最后一列,当我们要取的列很多不知道最后一列时可以使用   
29    config
31    ip.txt
1306  passwd
1306  test
47    user.txt

取出passwd的第一列和最后一列
[root@test1 data]# awk -F: '{print $1,$NF}' passwd |column -t
root              /bin/bash
bin               /sbin/nologin
daemon            /sbin/nologin
adm               /sbin/nologin
lp                /sbin/nologin
sync              /bin/sync
#将passwd第一列和最后一列交换,只需要$1和$NF
[root@test1 data]# awk -F: '{print $NF,$1}' passwd 
/bin/bash root
/sbin/nologin bin
/sbin/nologin daemon
/sbin/nologin adm
/sbin/nologin lp
2.3.3小结

行与列名称

awk取行与取列

取出网卡IP地址(同时取行取列)

#取出IP地址
[root@test1 ~]# ifconfig
ens160: flags=4163  mtu 1500
        inet 10.1.1.28  netmask 255.255.255.0  broadcast 10.1.1.255
        inet6 fe80::20c:29ff:fe23:2b1f  prefixlen 64  scopeid 0x20
[root@test1 ~]# ifconfig |awk 'NR==2' |awk -F"[ ]+" '{print $3}'
10.1.1.28  #("[ ]+"分隔符为空格,可能连续加上加号 $3第三列)
[root@test1 ~]# ifconfig |awk -F"[ ]+" 'NR==2{print $3}'
10.1.1.28 #('NR==2{print $3}'作为条件合并到一起)

2.4awk常见的内建变量(可以直接使用)

FS 列分隔符,指定每行文本的字段分隔符,默认为空格或者制表符,与-F作用相同
OFS 删除字段分割符(awk显示每一行的时候,每一列之间通过什么分割,默认空格)
NF 当前处理的行的字段个数
NR 当前处理行的行号(序数)
$0 当前处理的行的整行内容
$n 当前处理行的第n个字段(第n列)
FILENAME 被处理的文件名
RS 行分割符,预设值是‘\n’

2.5awk模式匹配

命令 选项 条件{动作}
awk -F"[ ]+" ‘NR==2{print $3}’
比较符号:>< >= <= == !=
正则
范围表达式
特殊条件:BEGIN和END
2.5.1比较表达式-参考取行部分
2.5.2正则
//支持扩展正则
可以精确到某一列中是否包含改内容(sed和grep比较难实现)
~包含
!~不包含
正则 awk正则
^表示以……开头的行 某一列的开头 $3~/^root/
$表示以……结尾的行 某一列的结尾 3   / r o o t 3~/root 3 /root/
^$表示空行 某一列是空的,很少用
#第三列以2开头的行
[root@test1 data]# awk -F: '$3 ~/^2/' passwd 
daemon:x:2:2:daemon:/sbin:/sbin/nologin
2.5.3表示范围
/哪里开始/,/哪里结束/常用
NF==1,NF==5 从第一行开始到第五行结束 类似于sed -n '1,5p'
#显示指定时间(11:02到11:02:30)范围内容的IP地址
awk '/11:02:00/,/11:02:30/{print $1}' access.log

2.5.4特殊模式BEGIN{}和END{}

模式 含义 应用场景
BEGIN{} 里面的内容会在awk读取文件之前执行 统计、计算、不涉及读取文件 用来处理文件之前,添加表头 定义awk变量(也可以用-v)
END{} 里面的内容会在awk读取文件之后执行 awk进行统计,一般过程:先进行计算,最后里面输出结果 awk使用数组,用来输出数组结果

常用统计方法:

统计方法 简写 应用场景
i=i+1 i++ 计数
sum=sum+??? sum+=??? 求和累加
array[]=array[]+1 array[]++ 数组分类计数
#统计空行
[root@test1 data]# awk '/^$/{i++}END{print i}' test1
10
#求1加到100的和
[root@test1 data]# seq 100 |awk '{sum=sum+$1}END{print sum}'
5050

2.6数组

统计日志:统计每个IP出现次数;统计每种状态出现次数;统计系统中每个用户被攻击的次数;统计攻击者IP出现次数
累加求和:统计每个IP消耗的流量;
shell数组 awk数组
形式 array[0]=0 array[1]=1 array[0]=0 array[1]=1
使用 echo $array[0] $array[1] print array[0] array[1]
批量输出数组内容 for i in ${array[*]} do echo $i done for (i in array) print array[i]
#awk数组案列
[root@test1 data]# awk 'BEGIN{a[0]=123456;a[1]="shixiao";print a[0],a[1]}'
123456 shixiao
[root@test1 data]# awk 'BEGIN{a[0]=123456;a[1]="shixiao";for(i in a)print a[i]}'
123456
shixiao
#上面是按需输出,下面是借助循环全部输出
2.6.1案列
[root@test1 data]# cat test1
http://www.shixiaohao.org/index.html
http://www.shixiaohoa.org/1.html
http://www.post.shixiaohao.org/index.html
http://mp3.shixiaohao.org/index.html
http://mp3.shixiaohao.org/index.html
http://post.shixiaohao.org/2.html
[root@test1 data]# awk -F"[/.]+" '{print $2}' test1
www
www
www
mp3
mp3
[root@test1 data]# awk -F"[/.]+" '{a[$2]++}END{for(i in a)print i,a[i]}' test1
www 3
mp3 2
post 1
[root@test1 data]# awk -F"[/.]+" '{a[$2]++}END{for(i in a)print i,a[i]}' test1|sort -rnk2 
www 3
post 2
mp3 2

2.7for循环

shell编程C语言for循环 awk for 循环
for(i=1;i<=10;i++) do echo $i done for (i=1;i<=10;i++) print i awk for循环用来循环每个字段
[root@test1 data]# awk 'BEGIN{for(i=1;i<=100;i++)sum+=i;print sum}'
5050

2.8if判断

shell if判断 awk if判断
if[i -eq 0];then echo " " fi if(条件) print " "
if[i -eq 0];then echo " " else echo " " fi if(条件) print " " else print " "
[root@test1 data]# df -h |awk -F"[ %]+" 'NR>1{if($5>10)print "disk not enough",$1}'
disk not enough /dev/sda1

注意:awk使用多个条件时,第一个条件可以放在‘条件{动作}’ 第二个条件 一般用if判断。

你可能感兴趣的:(linux,编辑器,服务器,运维)