19.1 awk工作原理

本博文目录索引

[TOC]


一、初识awk

(一)什么是awk?

awk,全称:Aho Weinberger Kernighan
是一个报告生成器,用于格式化文本输出

(二)awk能做什么?

1、主要功能:格式化显示文档、或者打印报表
2、将给定的文本内容按照工程师想要的格式输出显示、或者打印成报表格式
3、日常用途:处理各种文档(比如日志信息),从中分析挖掘出工程师关心的必要数据,并且打印成报表

(三)CentOS7系统中的awk

1、gawk

在CentOS7(或者CentOS6)系统中,使用GNU项目组开发的gawk来实现awk的功能

Gawk is the GNU Project's implementation of the AWK programming language.

2、awk是一个软链接,指向gawk

[root@Alvin ~]# ll /usr/bin/awk

软链接:/usr/bin/awk
真身:/usr/bin/gawk

STDOUT:
lrwxrwxrwx. 1 root 4 Mar 28 01:54 /usr/bin/awk -> gawk

(四)awk的基本语法

1、第一种语法格式

awk  [options]  'program'  var=VALUE  /PATH/TO/SOMEFILE...

(1)options:选项
(2)program:程序,使用awk语言,用单引号 '' 引起来
相对比较复杂,需要根据生产需求的逻辑关系编写awk程序代码,从而实现特定功能

2、第二种语法格式

awk  [options]  -f  programFile  var=VALUE  /PATH/TO/SOMEFILE...

(1)-f programFile:将逻辑复杂的awk程序代码放在programFile程序文件中,用 -f 调用awk程序文件

3、第三种语法格式

awk  [options]  'BEGIN{action;...}pattern{action;...}END{action;...}'  /PATH/TO/SOMEFILE...

(五)awk处理机制

1、逐行处理

(1)会在内存中开辟一块awk处理文本的内存空间
(2)每一次读入文件中的一行文本到内存空间进行处理
(4)自带循环:处理完第一行并输出,然后再读入第二行,以此类推

2、切割字段

(1)可以根据指定的分隔符,把读入的一行文本切割成若干的字段
(2)每个字段都有对应的变量来表示

变量 含义
$0 读入的整行
$1 第一个字段
$n 第n个字段

(3)默认的字段分隔符是 空白符 (空格、tab键)
(4)而且个数不限,多个连续的空白符被识别为一个空白符

(六)awk中的行与列

1、记录

(1)在awk中,把读入的一行称为“记录”,英文:record
(2)类似于Excel表的一行
(3)在awk中,一般需要手动指定“记录分隔符”,用来区分每一行
(4)默认使用 \n (回车换行符) 作为记录分隔符

2、字段

(1)在awk中,把切割后的每一列称为“字段”,英文:field
(2)类似于Excel表的每一列
(3)在awk中,一般需要手动指定“字段分隔符”,用来将读入的一行文本切割成若干的字段
(4)默认使用 空白符 (空格、tab键) 作为记录分隔符

3、小结

通用概念 awk概念 默认分隔符 解释
记录 \n 回车换行符
字段 空白符 空格、tab键

二、awk工作原理

(一)典型的语法格式

awk  [options]  'BEGIN{action;...}pattern{action;...}END{action;...}'  /PATH/TO/SOMEFILE...

(二)执行流程

  • 第一步:执行 BEGIN{action;...} 语句块,与文件无关
  • 第二步:从文件或者STDIN中读取一行,然后执行 pattern{action;...} 语句块,它逐行扫描文本内容,从第一行到最后一行重复这个过程,直到文本内容全部被读取完毕
  • 第三步:当读至输入流末尾时,执行 END{action;...} 语句块

(三)语句块使用场景

1、BEGIN语句块

BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如:变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中

2、END语句块

END语句块在awk从输入流中读取完所有的行之后即被执行,它也是一个可选语句块,比如:打印所有行的分析结果这类信息汇总都是在END语句块中完成

3、pattern语句块

pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块

(四)program

1、program的组合

program:pettern{action statements;...}

2、pattern

(1)是action动作语句的触发条件
(2)仅当满足pattern模式条件时,才会执行action动作语句
(3)类似于grep的“条件过滤”
(4)可以省略:没有定义过滤规则,所有行都满足要求

3、action

(1)是动作语句
(2)可以省略:省略时默认执行 print $0 操作

(五)用法举例

1、省略pattern:默认匹配所有行,执行action语句

[root@Alvin]# awk '{print "Hello AWK!"}' /etc/fstab

读取 /etc/fstab 文本的所有行,并在每一行的位置打印 Hello AWK!

STDOUT:若干行 Hello AWK!
Hello AWK!
[此处省略更多信息]

2、BEGIN语句:不处理文件,直接执行action语句

[root@Alvin ~]# awk 'BEGIN{print "Hello AWK!"}'

不处理任何文件,直接打印一行 Hello AWK!

STDOUT:
Hello AWK!

3、默认的字段分隔符

[root@Alvin ~]# df | awk '{print $1,$5}'

以默认的字段分隔符(空白符)将每一行文本切割若干字段,取出第一和第五个字段

STDOUT: 设备文件 空间利用率
/dev/sda1 11%
[此处省略更多信息]

4、 -F: 指定的字段分隔符

[root@Alvin ~]# awk -F: '{print $1":"$3}' /etc/passwd

指定 : 作为字段分隔符,将每一行文本切割成若干字段,取出第一和第三个字段

STDOUT: 用户名 : UUID
root:0
[此处省略更多信息]

冒号 : 需要用双引号 "" 引起来,当作一个普通字符串

5、借助管道:处理其他命令的标准输出

[root@Alvin ~]# tail -3 /etc/fstab | awk '{print $2,$4}'

将 tail 命令的标准输出作为 awk 的标准输入,默认以 空白符 为字段分隔符,将每一行文本切割成若干字段,取出第二和第四个字段

STDOUT: 挂载点 挂载选项
/boot defaults
[此处省略更多信息]

三、内置变量

(一)FS:字段分隔符(field separator)

(1)以指定的字段分隔符,将一行文本切割成若干字段
(2)省略不写时,默认以 空白符 作为字符分隔符处理一行文本

[root@Alvin ~]# awk -v FS=: '{print $1FS$3}' /etc/passwd

注意:
FS 作为变量使用时,不需要加 $ 符号!!!

STDOUT: 用户名 : UUID
root:0
[此处省略更多信息]

警告!
-F:
-v FS=:
以上两种写法等价,但是不要混淆!!!

(二)OFS:输出的字段分隔符(output field separator)

(1)以指定的字段分隔符,将输出的一行文本切割成若干字段
(2)省略不写时,默认以 空白符 作为字段分隔符处理输出的一行文本
(3)用来对输出信息进行格式化处理

[root@Alvin ~]# tail -3 /etc/fstab | awk -v OFS=: '{print $2,$3,$4}'

注意:
指定 OFS 之后,分隔符 , 会识别成指定的 OFS ,而不会是默认的 空白符 了!

STDOUT: 挂载点 : 文件系统类型 : 挂载选项
/boot:xfs:defaults
/data:xfs:defaults
swap:swap:defaults

(三)RS:记录分隔符(record separator)

(1)以指定的记录分隔符,将输入流切割成多行记录
(2)省略不写时,默认以 \n 作为记录分隔符处理输入流

[root@Alvin ~]# cat > f1
[root@Alvin ~]> a b:c
[root@Alvin ~]> d:f gg
[root@Alvin ~]# awk -v RS=: '{print $0}' f1

注意:
FS 指定 : 作为记录分隔符,替换默认的 \n ,将输入流切割成若干的行

STDOUT:
a b
c
d
f gg

(四)ORS:输出的记录分隔符(output record separator)

(1)以指定的记录分隔符,将输出流切割成多行记录
(2)省略不写时,默认以 \n 作为记录分隔符处理输出流
(3)用来对输出信息进行格式化处理

[root@Alvin ~]# cat > f1
[root@Alvin ~]> a b:c
[root@Alvin ~]> d:f gg
[root@Alvin ~]# awk -v ORS="---" '{print $0}' f1

注意!
$0 表示将整行输出

STDOUT: 将回车换行符替换为 ---
a b;c---d;f gg---

(五)NF:字段数量(number of field)

(1)NF 表示一行文本中有多少个字段(需要指定字段分隔符)
(2)$NF 表示最后一个字段的值

[root@Alvin ~]# awk -v FS=: '{print NF,$NF,$(NF-1)}' /etc/passwd

注意!
$NF 表示最后一个字段的值
$(NF-1) 表示倒数第二个字段的值

STDOUT: 字段数量为7 第7个字段的值 第6个字段的值
7 /bin/bash /root
[此处省略更多信息]

(六)NR:记录编号(number of record)

(1)NR 表示当前行在输入流中处于第几行
(2)默认会将多个文本合并为一个输入流(需要指定记录分隔符)

[root@Alvin ~]# awk -v FS=: '{print NR,$1}' /etc/passwd

注意!
多个文件会被合并到同一个输入流中去!

STDOUT: 当前行的编号 用户名
1 root
2 bin
[此处省略更多信息]

(七)FNR:按文件计算“记录编号”(file (1)FNR 表示当前行在不同输入流中处于第几行

(2)遇到多个文本会当做多个不同的输入流来对待(需要指定记录分隔符)

[root@Alvin ~]# awk -v FS=: '{print FNR,$1}' /etc/passwd /etc/shadow

STDOUT: 在当前文件中的当前行的编号 用户名
1 root
2 bin
[此处省略更多信息]
1 root
2 bin
[此处省略更多信息]

(八)FILENAME:文件名

[root@Alvin ~]# awk -v FS=: '{print FILENAME}' /etc/passwd

STDOUT: 若干行 文件名
/etc/passwd
[此处省略更多信息]

(九)ARGC:参数个数(arguments account)

(1)统计命令的参数个数
(2)$0 代表 awk 命令本身
(3)$1 代表后面跟的参数列表的第一个

[root@Alvin ~]# awk '{print ARGC}' /etc/passwd

STDOUT: 当前命令的参数个数
2

(十)ARGV:参数列表数组(arguments variable)

(1)把参数列表写入ARGV数组
(2)数组下标的范围:[0,命令的参数个数]

[root@Alvin ~]# awk '{print ARGV[0],ARGV[1]}' /etc/passwd

STDOUT: 第一个参数 第二个参数
awk /etc/passwd

四、自定义变量

(一)声明自定义变量的方法

1、使用 -v 选项

-v var=VALUE

[root@Alvin ~]# awk -v var="name" 'BEGIN{print var}'

STDOUT:
name

2、在action语句块中

'{var=VALUE;...}'

[root@Alvin ~]# awk 'BEGIN{var="name";print var}'

STDOUT:
name

(二)自定义变量使用的原则

先声明赋值,然后再引用!!

五、printf

(一)printf特性

1、FORMAT

(1)必须定义格式:FORMAT
(2)按照一定的格式来输出

2、格式的语法

(1)FORMAT中需要分别为后面每一个item定义对应的“格式符”
(2)第几个格式定义对应第几个变量
(3)有多少个 % 表示后面定义了多少个变量

3、换行

默认不会自动换行,需要显式给出换行控制符 \n

(二)语法格式

printf  "FORMAT\n",item1,item2,...

注意!
先写格式定义,再写变量值
需要使用 \n 来实现自动换行

(三)格式符

格式符 含义
%d 显示十进制整数
%f 显示浮点数
%s 显示字符串
%% 显示 % 本身

(四)修饰符

在 % 后面加修饰符

修饰符 含义 举例 说明
# 显示具体内容的宽度 %15s 宽度为15个字符
#.# 表示小数点的精度 %3.1f 精度为一位小数
- 左对齐 %-s
默认右对齐 %s
+ 显示数值的正负符号 %-d

(五)举例

[root@Alvin ~]# awk -v FS=: '{printf "%-10s:%6d\n",$1,$3}' /etc/passwd

说明:
(1)%-10s 表示:以字符串格式显示、宽度是10个字符、使用左对齐
(2)%6d 表示:以十进制整数格式显示、宽度是6个字符、默认右对齐
(3)使用 \n 来实现自动换行

STDOUT: 用户名 : UUID
root : 0
bin : 1
daemon : 2
[此处省略更多信息]

猜你喜欢

转载自www.cnblogs.com/GymUManAlvin/p/9043421.html