awk高级用法

一、AWK介绍

awk格式由 参数+模式+ 动作组成

  • 参数:如-F 分隔符等
  • 模式:即pattern,可以理解为sed的匹配模式,可以是表达式,也可以理解成是一个条件
  • 动作:action,是由大括号内的一条或者多条语句组成,用逗号分开
awk [options]  'pattern {action}' file

在这里插入图片描述

处理的内容可以来自标准输入或者文本以及管道等

二、内置变量

变量含义功能
FIELDWIDTHS由空格分隔的一列数字,定义了每个数据字段的确切宽度
NRnumber of record输入流的当前记录编号,已经读出的记录数
RS输入记录分隔符,默认为换行符 = 行分隔符
ORS输出记录分隔符,默认为换行符
NFnumber of fieldNF表示当前行分割后的最后一列(0 和NF均为内置变量)NF表示最后一个字段,NF表示当前行被分隔符切开以后,一共有几个字段。假如一行文本被空格分成了7段,那NF值就是7
FSfield separator输入字段分隔符 = 区域分隔符,列分隔符
OFS输出字段分隔符,默认为空格

2.1 区域和记录

名称含义
field区域、字段,如$1 、$2 、$NF,$代表取或者引用的意思
record记录,默认一整行 如 $0

在这里插入图片描述

2.2 NR (number of record)行记录数

查看行号大于等于2的全部行 或者大于等于2小于10的行,并显示行号

 awk 'NR>=2 {print NR,$0}'  /etc/passwd
awk 'NR>=2&&NR<10 {print NR,$1,$NF}'  /etc/passwd
或者
awk 'NR==2,NR==10 {print NR,$1,$NF}'  /etc/passwd  也表示从第2-10行

在这里插入图片描述
在这里插入图片描述

2.3 NF (number of f)列记录数

NF代表按照某一个分隔符统计列的总数,$NF代表打印出最后一列内容

1) NF用法

按照句号分割,每一行共计多少列
[root@xiyu_master /root]
#cat date-2.log 
2022.03.130000
20220313-18:00
18.00.12

[root@xiyu_master /root]
#cat date-2.log |awk -F . '{print NF}'
3
1
3

2) $NF用法

倒数最后一列

[root@xiyu_master /root]
#cat date-1.log |awk -F , '{print $NF}'
date2005
date2015
date2025

倒数第二列
[root@xiyu_master /root]
#cat date-1.log |awk -F , '{print $(NF-1)}'
date2004
date2014
date2024

在这里插入图片描述

2.3 FS与OFS 行分隔符的输入和输出

目标:将逗号(,)分隔符更换成 横杠(-)分隔符,FS代表输入分隔符,OFS代表输出的分隔符

[root@localhost ~]# cat date-1.log
date2000,date2001,date2002,date2003,date2004,date2005
date2010,date2011,date2012,date2013,date2014,date2015
date2020,date2021,date2022,date2023,date2024,date2025

#awk 'BEGIN{FS=","; OFS="-"} {print $1,$2,$3}' date-1.log
date2000-date2001-date2002
date2010-date2011-date2012
date2020-date2021-date2022

在这里插入图片描述

2.4 RS与ORS 列分隔符的输入和输出

变量 RS 和 ORS 定义了 awk 程序如何处理数据流中的字段,默认情况下,awk 将 RS 和 ORS 设为换行符。默认的 RS 值表明,输入数据流中的每行新文本就是一条新纪录。 有时,你会在数据流中碰到占据多行的字段。典型的例子是包含地址和电话号码的数据,其中地址和电话号码各占一行,例如:
在这里插入图片描述
RS代表行分隔符,RS=":",意思就是将目前:换成回车,RS=""代表将分隔符清空,就代表全部在一行

[root@xiyu_master /root]#cat information.log
xi yu
999 yuhang Street
Yuhang District
(0571)88219999

qing chen
999 yuhang Street
Yuhang District
(0572)88218888

xiao ye
998 yuhang Street
Yuhang District
(0573)88216666

将换行变成空格,输出1和4列
[root@xiyu_master /root]#awk 'BEGIN{FS="\n"; RS=""} {print $1,$4}' information.log
xi yu (0571)88219999
qing chen (0572)88218888
xiao ye (0573)88216666

在这里插入图片描述

2.5 BEGIN与END

其中:BEGIN和END中的语句分别在开始读取文件(in_file)之前和读取完文件之后发挥作用,可以理解为初始化和扫尾。

awk [-参数 变量] ‘BEGIN{初始化}条件类型1{动作1}条件类型2{动作2}。。。。END{后处理}’

目标:取passwd中$3中大于20以上的行,使用到变量a进行递增,最后输出一个总数

awk -F ":" '$3>15{a++;print $0}' /etc/passwd  #输出符合条件的所有行
awk -F ":" '$3>15{a++}END{print a}' /etc/passwd #输出最后一个总数

2.6 FIELDWIDTH

设置了 FIELDWIDTH 变量,awk 就会忽略 FS 变量,并根据提供的字段宽度来计算字段,输入3,则代表3个字段放一起,默认空格为分隔符

[root@xiyu_master /root]
#cat date-2.log
2022.03.130000
20220313-18:00
18.00.12

[root@xiyu_master /root]
#awk 'BEGIN{FIELDWIDTHS="3 5 2 5"}{print $1,$2,$3,$4}' date-2.log
202 2.03. 13 0000
202 20313 -1 8:00
18. 00.12

在这里插入图片描述
注意:一旦设定了 FIELDWIDTHS 变量的值,就不能再改变了,因此,这种方法并不适用于变长的字段

三、正则表达式

3.1 表达式符号

^ 开头  /^test/
$ 结尾 /test$/
\* 匹配0个或者多个前导字符
\?  匹配0个1个前导字符
\. 匹配任意单个字符
[] 匹配指定字符组内的任意一个字符
[] 匹配不在指定字符组内的任意一个字符
~ 代表对记录或者字段的表达式进行匹配
~ 代表~取反

3.2 正则实践

目标:查找mysql开头的行
说明://固定格式,以什么开头用^
#cat /etc/passwd |awk '/^mysql/{print $0}'
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/false
目标:取第一列以s开头的行
说明:先定义区域,~代表匹配后面条件 //固定格式,以什么开头用^
[root@xiyu_master /root]
#cat /etc/passwd |awk '$1~/^s/{print $0}'
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
目标:匹配最后一个字段为/bin/bash的行
[root@xiyu_master /root]
#awk '$NF~/bin/bash{print $0}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
elsearch:x:1000:1000::/home/elsearch:/bin/bash
www:x:1001:1001::/home/www:/bin/bash

四、案例

4.1 案例一、统计passwd每个单词的重复数量

思路:需要将所有行中按照:进行列排,然后排序,统计

cat /etc/passwd |awk 'BEGIN{RS=":"}{print $0}'|egrep -o [a-zA-Z]+  |sort  |uniq -c|sort -rn
或者:  RS=" " 内部可以同时使用多个分隔符,如下 / - 空格 :
cat /etc/passwd |awk 'BEGIN{RS="/- :"}{print $0}'|egrep -o "[a-zA-Z]+"|sort -rn |uniq -c

在这里插入图片描述

4.2 案例二、过滤IP地址

目标:取IP地址
思路:先将第二排取出来,使用NR==2 ,然后再将行分隔符定为空格,取第二个区域即可

[root@xiyu_master /root]
#ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.19.84.181  netmask 255.255.240.0  broadcast 172.19.95.255
        ether 00:16:3e:14:32:7a  txqueuelen 1000  (Ethernet)
        RX packets 6920718  bytes 1401311001 (1.3 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5003571  bytes 2374606077 (2.2 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@xiyu_master /root]
#ifconfig eth0 |awk 'NR==2&&FS=" " {print $2}'
172.19.84.181

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值