文本处理三剑客之awk

本文详细介绍了awk的工作原理、基本用法,包括BEGIN和END语句块、模式匹配、输出格式化、变量与控制语句等。通过实例展示了如何进行文本处理,如打印特定行、处理IP地址、分区利用率等。同时,讲解了awk中的内置变量,如FS、OFS、NR、FNR等,以及自定义变量的设置。此外,还涵盖了条件判断、循环结构和数组操作。最后,提到了awk的函数和脚本编写,是学习awk进行文本分析和数据处理的实用指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.awk 工作原理和基本用法说明

awk Aho, Weinberger, Kernighan ,报告生成器,格式化文本输出, GNU/Linux 发布的 AWK目前由自 由软件基金会( FSF )进行开发和维护,通常也称它为 GNU AWK
有多种版本:
  • AWK:原先来源于 AT & T 实验室的的AWK
  • NAWKNew awkAT & T 实验室的AWK的升级版
  • GAWK:即GNU AWK。所有的GNU/Linux发布版都自带GAWK,它与AWKNAWK完全兼容
GNU AWK 用户手册文档
https://www.gnu.org/software/gawk/manual/gawk.html
gawk :模式扫描和处理语言,可以实现下面功能
  • 文本处理
  • 输出格式化的文本报表
  • 执行算数运算
  • 执行字符串操作
格式:
awk [options]   'program' var=value   file…
awk [options]   -f programfile    var=value file…
说明:
program 通常是被放在单引号中,并可以由三种部分组成
  • BEGIN语句块
  • 模式匹配的通用语句块
  • END语句块

常见选项:
  • -F “分隔符指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符
  • -v var=value 变量赋值
Program 格式:
pattern{action statements;..}
pattern :决定动作语句何时触发及触发事件,比如: BEGIN,END, 正则表达式等
action statements :对数据进行处理,放在 {} 内指明,常见: print, printf
awk 工作过程
第一步:执行 BEGIN{action;… } 语句块中的语句
第二步:从文件或标准输入 (stdin) 读取一行,然后执行 pattern{ action;… }语句块,它逐行扫描文件, 从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行 END{action;…} 语句块
BEGIN 语句块在 awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打 印输出表格的表头等语句通常可以写在 BEGIN 语句块中
END 语句块在 awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总 都是在 END 语句块中完成,它也是一个可选语句块
pattern 语句块中的通用命令是最重要的部分,也是可选的。如果没有提供 pattern 语句块,则默认执行{ print } ,即打印每一个读取到的行, awk 读取的每一行都会执行该语句块

分割符、域和记录
  • 由分隔符分隔的字段(列column,field)标记$1,$2...$n称为域标识,$0为所有域,注意:和 shell中变量$符含义不同
  • 文件的每一行称为记录record
  • 如果省略action,则默认执行 print $0 的操作
常用的 action 分类
  • output statementsprint,printf
  • Expressions:算术,比较表达式等
  • Compound statements:组合语句
  • Control statementsif, while
  • input statements
awk 控制语句
  • { statements;… } 组合语句
  • if(condition) {statements;…}
  • if(condition) {statements;…} else {statements;…}
  • while(conditon) {statments;…}
  • do {statements;…} while(condition)
  • for(expr1;expr2;expr3) {statements;…}
  • break
  • continue
  • exit

2.动作 print

格式
print item1, item2, ...
说明:
  • 逗号分隔符
  • 输出item可以字符串,也可是数值;当前记录的字段、变量或awk的表达式
  • 如省略item,相当于print $0
  • 固定字符符需要用“ ” 引起来,而变量和数字不需要
范例:取出网站访问量最大的前 3 IP
[root@VM_0_10_centos logs]# awk '{print $1}' nginx.access.log-20200428|sort | 
uniq -c |sort -nr|head -3
   5498 122.51.38.20
   2161 117.157.173.214
    953 211.159.177.120
[root@centos8 ~]#awk '{print $1}' access_log |sort |uniq -c|sort -nr|head 
   4870 172.20.116.228
   3429 172.20.116.208
   2834 172.20.0.222
   2613 172.20.112.14
   2267 172.20.0.227
   2262 172.20.116.179
   2259 172.20.65.65
   1565 172.20.0.76
   1482 172.20.0.200
   1110 172.20.28.145
范例:取出分区利用率
[root@centos8 ~]# df | awk -F"[[:space:]]+|%" '{print $5}'
Use
0
0
1
0
3
19
1
0

范例: ifconfig 输出结果中的IP地址

[root@centos8 ~]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.0.85  netmask 255.255.255.0  broadcast 10.0.0.255
        inet6 fe80::20c:29ff:fe3d:d1e7  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:3d:d1:e7  txqueuelen 1000  (Ethernet)
        RX packets 24590  bytes 25224965 (24.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 12793  bytes 4232673 (4.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@centos8 ~]# ifconfig eth0 | sed -n "2p"
        inet 10.0.0.85  netmask 255.255.255.0  broadcast 10.0.0.255
[root@centos8 ~]# ifconfig eth0 | sed -n "2p" | awk '{print $2}'
10.0.0.85

[root@centos8 ~]# ifconfig eth0 | awk '/netmask/{print $2}'
10.0.0.85

[root@centos8 ~]# ifconfig eth0 | awk 'NR==2{print $2}'
10.0.0.85

3.awk 变量

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

3.1常见的内置变量

  • FS:输入字段分隔符,默认为空白字符,功能相当于 -F

范例:

[root@centos8 ~]#awk -v FS=":" '{print $1FS$3}' /etc/passwd |head -n3
root:0
bin:1
daemon:2
  • OFS:输出字段分隔符,默认为空白字符

范例:

[root@centos8 ~]#awk -v FS=':'   '{print $1,$3,$7}'   /etc/passwd|head -n1
root 0 /bin/bash
[root@centos8 ~]#awk -v FS=':' -v OFS=':' '{print $1,$3,$7}'   
/etc/passwd|head -n1
root:0:/bin/bash
  • RS :输入记录 record 分隔符,指定输入时的换行符
范例:
awk -v RS=' ' '{print }' /etc/passwd
  • ORS :输出记录分隔符,输出时用指定符号代替换行符
范例:
awk -v RS=' ' -v ORS='###'  '{print $0}' /etc/passwd
  • NF:字段数量
范例:
#引用变量时,变量前不需加$
[root@centos8 ~]#awk -F:'{print NF}' /etc/fstab 
[root@centos8 ~]#awk -F:'{print $(NF-1)}' /etc/passwd
[root@centos8 ~]#ls /misc/cd/BaseOS/Packages/*.rpm |awk -F"." '{print $(NF-
1)}'|sort |uniq -c
    389 i686
    208 noarch
   1060 x86_64
  • NR :记录的编号
范例:
[root@centos8 ~]#awk '{print NR,$0}' /etc/issue /etc/centos-release
1 \S
2 Kernel \r on an \m
34 CentOS Linux release 8.1.1911 (Core)
  •  FNR :各文件分别计数,记录的编号
范例:
awk '{print FNR}' /etc/fstab /etc/inittab
[root@centos8 ~]#awk '{print NR,$0}' /etc/issue /etc/redhat-release 
1 \S
2 Kernel \r on an \m
34 CentOS Linux release 8.0.1905 (Core) 
[root@centos8 script40]#awk '{print FNR,$0}' /etc/issue /etc/redhat-release 
1 \S
2 Kernel \r on an \m
31 CentOS Linux release 8.0.1905 (Core)
  • FILENAME :当前文件名
范例:
[root@centos8 ~]#awk '{print FILENAME}' /etc/fstab
[root@centos8 ~]#awk '{print FNR,FILENAME,$0}' /etc/issue /etc/redhat-release 
1 /etc/issue \S
2 /etc/issue Kernel \r on an \m
3 /etc/issue 
1 /etc/redhat-release CentOS Linux release 8.0.1905 (Core)
  • ARGC :命令行参数的个数
范例:
[root@centos8 ~]#awk '{print ARGC}' /etc/issue /etc/redhat-release 
3
3
3
3
[root@centos8 ~]#awk 'BEGIN{print ARGC}' /etc/issue /etc/redhat-release 
3
  • ARGV :数组,保存的是命令行所给定的各参数,每一个参数: ARGV[0] ......
范例:
[root@centos8 ~]#awk 'BEGIN{print ARGV[0]}' /etc/issue /etc/redhat-release 
awk
[root@centos8 ~]#awk 'BEGIN{print ARGV[1]}' /etc/issue /etc/redhat-release 
/etc/issue
[root@centos8 ~]#awk 'BEGIN{print ARGV[2]}' /etc/issue /etc/redhat-release 
/etc/redhat-release
[root@centos8 ~]#awk 'BEGIN{print ARGV[3]}' /etc/issue /etc/redhat-release 
[root@centos8 ~]#

3.2自定义变量

自定义变量是区分字符大小写的 , 使用下面方式进行赋值
  • -v var=value
  • program中直接定义
范例:  
[root@centos8 ~]#awk -v test1=test2="hello,gawk" 'BEGIN{print test1,test2}'   
test2=hello,gawk 
[root@centos8 ~]#awk -v test1=test2="hello1,gawk" 
'BEGIN{test1=test2="hello2,gawk";print test1,test2}'   
hello2,gawk hello2,g

4.动作 printf

printf 可以实现格式化输出
格式:
printf “FORMAT”, item1, item2, ...
说明:
  • 必须指定FORMAT
  • 不会自动换行,需要显式给出换行控制符 \n
  • FORMAT中需要分别为后面每个item指定格式符
格式符:与 item 一一对应
%s :显示字符串
%d, %i :显示十进制整数
%f :显示为浮点数
%e, %E :显示科学计数法数值
%c :显示字符的 ASCII
%g, %G :以科学计数法或浮点形式显示数值
%u :无符号整数
%% :显示 % 自身
修饰符
#[.#] 第一个数字控制显示的宽度;第二个 # 表示小数点后精度,如: %3.1f
- 左对齐(默认右对齐) 如: %-15s
+   显示数值的正负符号   如: % + d
范例:
awk -F:   '{printf "%s",$1}' /etc/passwd
awk -F:   '{printf "%s\n",$1}' /etc/passwd
awk -F:   '{printf "%20s\n",$1}' /etc/passwd
awk -F:   '{printf "%-20s\n",$1}' /etc/passwd
awk -F:   '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
awk -F:   '{printf "Username: %s\n",$1}' /etc/passwd
awk -F:   '{printf “Username: %sUID:%d\n",$1,$3}' /etc/passwd
awk -F:   '{printf "Username: %25sUID:%d\n",$1,$3}' /etc/passwd
awk -F:   '{printf "Username: %-25sUID:%d\n",$1,$3}'

5.操作符

算术操作符:

x+y, x-y, x*y, x/y, x^y, x%y
-x :转换为负数
+x :将字符串转换为数值
字符串操作符:没有符号的操作符,字符串连接
赋值操作符:
=, +=, -=, *=, /=, %=, ^= ++, --
范例:
[root@centos8 ~]#awk 'BEGIN{i=0;print i++,i}'
0 1
[root@centos8 ~]#awk 'BEGIN{i=0;print ++i,i}'
1 1
比较操作符:
==, !=, >, >=, <, <=
范例:取奇,偶数行
[root@centos8 ~]#seq 10 | awk 'NR%2==0'
2
4
6
8
10
[root@centos8 ~]#seq 10 | awk 'NR%2==1'
1
3
5
7
9
模式匹配符:
~ 左边是否和右边匹配,包含关系
!~ 是否不匹配
范例:
[root@centos8 ~]#awk -F: '$0 ~ /root/{print $1}' /etc/passwd
[root@centos8 ~]#awk -F: '$0 ~ "^root"{print $1}' /etc/passwd
[root@centos8 ~]#awk '$0 !~ /root/'   /etc/passwd
[root@centos8 ~]#awk '/root/'   /etc/passwd
[root@centos8 ~]#awk -F: '/r/' /etc/passwd
[root@centos8 ~]#awk -F: '$3==0'     /etc/passwd
[root@centos8 ~]#df | awk -F"[[:space:]]+|%" '$0 ~ /^\/dev\/sd/{print $5}'
51
92
[root@centos8 ~]#ifconfig eth0 | awk 'NR==2{print $2}'
10.0.0.8
逻辑操作符:
与: && ,并且关系
或: || ,或者关系
非: ! ,取反
范例:
[root@centos8 ~]#awk 'BEGIN{print !i}'
1
[root@centos8 ~]#awk -v i=10 'BEGIN{print !i}'
0
[root@centos8 ~]#awk -v i=-3 'BEGIN{print !i}'
0
[root@centos8 ~]#awk -v i=0 'BEGIN{print !i}'
1
[root@centos8 ~]#awk -v i=abc 'BEGIN{print !i}'
0
条件表达式(三目表达式)
selector?if-true-expression:if-false-expression

6.模式PATTERN

PATTERN: 根据 pattern 条件,过滤匹配的行,再做处理
  • 如果未指定:空模式,匹配每一行
范例 :
[root@centos8 ~]#awk -F: '{print $1,$3}' /etc/passwd
  • /regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来
  • relational expression: 关系表达式,结果为才会被处理
        真:结果为非0 值,非空字符串
        假:结果为空字符串或0
  • line ranges:行范围
  • 不支持直接用行号,但可以使用变量NR间接指定行号
        /pat1/,/pat2/ 不支持直接给出数字格式
  • BEGIN/END模式
        BEGIN{}:仅在开始处理文件中的文本之前执行一次
        END{}:仅在文本处理完成之后执行一次

7.条件判断 if-else

语法:
if(condition){statement;…}[else statement]
if(condition1){statement1}else if(condition2){statement2}else if(condition3)
{statement3}...... else {statementN}
使用场景:对 awk 取得的整行或某个字段做条件判断

8.条件判断 switch

语法:
switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or 
/REGEXP2/: statement2; ...; default: statementn}

9.循环 while

语法:
while (condition) {statement;…}
条件 ,进入循环;条件 ,退出循环
使用场景:
        对一行内的多个字段逐一类似处理时使用
        对数组中的各元素逐一处理时使用

10.循环 do-while

语法:
do {statement;…}while(condition)
意义:无论真假,至少执行一次循环体
do-while 循环
语法: do {statement;…}while(condition)
意义:无论真假,至少执行一次循环体

11.循环 for

语法:
for(expr1;expr2;expr3) {statement;…}
常见用法:
for(variable assignment;condition;iteration process) {for-body}

特殊用法:能够遍历数组中的元素

for(var in array) {for-body}

12.continue break

continue 中断本次循环
break 中断整个循环
格式:
continue [n]
break [n]

13.next

next 可以提前结束对本行处理而直接进入下一行处理( awk 自身循环)

14.数组

awk 的数组为关联数组
格式
array_name[index-expression]
index-expression
  • 利用数组,实现 k/v 功能
  • 可使用任意字符串;字符串要使用双引号括起来
  • 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为空串
  • 若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历

15.awk 函数

awk 的函数分为内置和自定义函数

官方文档
https://www.gnu.org/software/gawk/manual/gawk.html#Functions

15.1常见内置函数

  • 数值处理:
rand():返回0和1之间一个随机数
srand():配合rand() 函数,生成随机数的种子
int():返回整数
  • 字符串处理:
length([s]):返回指定字符串的长度
sub(r,s,[t]):对t字符串搜索r表示模式匹配的内容,并将第一个匹配内容替换为s
gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容
split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第
一个索引值为1,第二个索引值为2,…
  • 可以awk中调用shell命令
system('cmd')
空格是 awk 中的字符串连接符,如果 system 中需要使用 awk 中的变量可以使用空格分隔,或者说
除了 awk 的变量外其他一律用 "" 引用起来
  • 时间函数
官方文档 : 时间函数
https://www.gnu.org/software/gawk/manual/gawk.html#Time-Functions
systime() 当前时间到1970年1月1日的秒数
strftime() 指定时间格式  

15.2 自定义函数

自定义函数格式:
function name ( parameter, parameter, ... ) {
   statements
   return expression
}

16.awk 脚本

awk 程序写成脚本,直接调用或执行
awk 脚本传递参数
格式:
awkfile  var=value  var2=value2... Inputfile
注意:在 BEGIN 过程中不可用。直到首行输入完成以后,变量才可用。可以通过 -v 参数,让 awk在执行 BEGIN 之前得到变量的值。命令行中每一个指定的变量都需要一个 -v 参数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值