目录
一、概述
1.2、工作原理
1.3、工作流程
1.4、 运行模式
1.5、 执行流程
1.6、 基本语法
二、实战案列
2.1、内建变量
2.2、内置变量
2.3、BEGIN 和 END 运算
一、概述
20世纪70年代诞生于贝尔实验室,现在centos7用的是gawk。
AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。
之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符
linux中有三剑客之称:
三剑客功能:
[awk]: 处理文本
grep : 过滤文本
sed : 修改文本
awk:全称Aho, Weinberger, Kernighan,报告生成器,格式化文本输出,GNU/Linux发布的AWK目前由自 由软件基金会(FSF)进行开发和维护,通常也称它为 GNU AWK。 它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描、过滤、统计汇总工作 数据可以来自标准输入也可以是管道或文件。
有多种版本:
- AWK: 原先来源于 AT & T 实验室的的AWK
- NAWK:New awk,AT & T 实验室的AWK的升级版
- GAWK:即GNU AWK。所有的GNU/Linux发布版都自带GAWK,它与AWK和NAWK完全兼容
在
linux
上常用的是
gawk,awk
是
gawk
的链接文件
1.2、工作原理
1. 初始化阶段
- 在处理文件之前,
awk
会执行BEGIN语句块(如果存在)。BEGIN语句块主要用于初始化变量、设置输出格式等准备工作,它与文件内容无关,只执行一次。
2. 逐行处理阶段
awk
逐行读取输入文件(或标准输入)的内容。对于每一行,它会执行以下操作:
- 分割字段:根据指定的字段分隔符(默认为空格或制表符),将当前行分割成多个字段。每个字段都可以通过内置的变量(如
$1
、$2
等)来访问。 - 模式匹配:检查当前行是否匹配用户定义的模式(如果有的话)。模式可以是正则表达式、条件表达式等。
- 执行操作:如果当前行匹配了模式,则执行与该模式相关联的操作。操作可以包括打印文本、计算表达式、赋值变量等。
- 重复处理:这个过程会重复进行,直到文件中的所有行都被处理完毕。
3. 汇总阶段
- 在处理完所有行之后,
awk
会执行END语句块(如果存在)。END语句块主要用于输出汇总信息、执行清理工作等,也只执行一次。
当读到第一行时,匹配条件,然后执行指定动作,再接着读取第二行数据处理,不会默认输出
如果没有定义匹配条件默认是匹配所有数据行,
awk
隐含循环,条件匹配多少次动作就会执行多少次逐行读取文本,默认以空格或tab
键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按 模式或者条件执行编辑命令。
sed
命令常用于一整行的处理,而
awk
比较、倾向于将一行分成多个
""
字段
"
然后再进行处理。
awk
信息的读入也是逐行读取的,执行结果可以通过
print
的功能将字段数据打印显示。
在使用
awk
命令的过程中,
可以使用逻辑操作符
" &&"
表示
"
与
"
、
"||
表示
"
或
"
、
"!"
表示非
";
还可以进行简单的数学运算,如
+
、 *、
/
、
%
、
^
分别表示加、减、乘、除、取余和乘方。
任何 awk 语句都是由模式和动作组成,一个 awk 脚本可以有多个语句。
模式决定动作语句的触发条件和触发时间
模式是一个条件表达式,用于决定哪些输入行应该被处理。模式可以是以下几种类型之一:
- 正则表达式:如果当前行与给定的正则表达式匹配,则执行相应的动作。
- 关系表达式:如果当前行的字段满足某个条件(如大于、小于等),则执行相应的动作。
- BEGIN和END模式:
BEGIN
模式在读取任何输入行之前执行一次,而END
模式在所有输入行都被读取和处理之后执行一次。 - 空模式:如果没有指定模式,则对所有输入行执行动作
动作是当模式匹配时执行的语句块。它通常包含awk
命令,用于对输入行或字段进行处理,如打印、赋值、计算等。动作可以是一个或多个awk
语句,这些语句被大括号{}
包围
1.3、 运行模式
- 正则表达式 : /root/ 匹配含有 root 的行 /*.root/
- 关系表达式: < > && || + *
- 匹配表达式: ~ !~ 动作:
- 变量 、命令、 内置函数 、流控制语句 它的语法结构如下:
1.4、 执行流程
BEGIN
语句设置计数和打印头部信息,在任何动作之前进行
END
语句输出统计结果,在完成动作之后执行
AWK
执行的流程非常简单:读(
Read
)、执行(
Execute
)与重复(
Repeat
)。
下面的流程图描述出 了AWK
的工作流程
BEGIN后面的花括号内容优先处理,BEGIN后的动作完成后再处理后面的
1.5、 基本语法
命令格式
如果动作较为复杂,也可以将动作写在一个单独的文件中,并使用
-f
选项来指定该文件:
awk -f
脚本文件
文件
1
文件
2 ..
格式:
awk
选项
命令部分
'{xxxx}'
文件名
二、实战案列
2.1、内建变量(重要)
内建变量(也称为内置变量或预定义变量,可直接使用)
awk
包含几个特殊的内建变量(可直接用)如下所示:
FS
:
指定
每行文本的字段
分隔符
,默认为空格或制表位。
NF
:当前处理的
行的字段个数
。
NR
:当前处理的
行的行号
(序数)。
$0
:当前处理的行的
整行内容
。
$n
:当前处理行的第
n
个字段(第
n
列)。
FILENAME
:被处理的文件名。
RS:
行分隔符。
awk
从文件上读取资料时
,
将根据
Rs
的定义把资料切割成许多条记录
,
而
awk
一次仅读入一 条记录,
以进行处理。预设值是
" \n'
简说:数据记录分隔,默认为
\n
,即每行为一条记录
变量名 | 描述 |
---|
FS | 指定每行文本的字段分隔符,默认为空格或制表位。 |
NF | 当前处理的行的字段个数(即列的个数)。 |
NR | 当前处理的行的行号(序数)。 |
$0 | 当前处理的行的整行内容。 |
$n | 当前处理行的第n个字段(第n列),其中n是一个数字。例如:$1 表示第一个字段,$2 表示第二个字段。 |
FILENAME | 被处理的文件名(当前输入文件的名)。 |
FNR | 各文件分别计数的行号,对于每个新文件,FNR 会从1开始重新计数。 |
OFS | 输出字段分隔符(默认值是一个空格)。 |
ORS | 输出记录分隔符(默认值是一个换行符)。 |
RS | 行分隔符。awk从文件上读取资料时,将根据RS 的定义把资料切割成许多条记录,awk一次仅读入一条记录进行处理。预设值是\n ,即每行为一条记录。 |
①、FS的作用
FS指定分隔符为: 并且$1 第一列
②、NF
的作用
即列的个数
打印每一行的列数,列的个数
③、NR的作用
行号
④、 $0的作用
一整行内容
它包含一个模式(/root/
)和一个动作({print $0}
)。
/root/
:这是一个正则表达式模式,用于匹配包含“root”的行。当 awk
扫描到匹配这个模式的行时,就会执行后面的动作。
awk -F: '/root/{print $0}' /etc/passwd
搜索包含root的整行内容,全部打印出来
⑤、$n(1>n为数字)的作用
awk
默认把这一行当做一列,因为没有被空格分隔,
awk
默 认以空格或tab
键分隔
awk '{print $1}' /etc/passwd
⑥、FILENAME(filename)的作用
就是提示处理文件的名字
⑦、FNR的使用
记录行号顺序
⑧、OFS的使用
分隔符为空格,输出分隔符为@@
默认情况下,OFS
的值是空格。
⑨、RS的用法
行分隔符,注意是行
分行的时候按照---来分割
变成=这样了
record1
record2
record3 iiii a1
b2
c3
$1是列
F或者FS是只有看列的时候,才会按照---来分隔(分列的的时候按照---来分割)
⑩、ORS
在每行后添加行分隔符
NF的作用
NR的作用
显示行号
awk -F: '{print "第" NR "行有" NF "列" }' /etc/passwd
在打印一遍
awk '{print "hello" }' </etc/passwd
直接打印内容
自定义冒号为分隔符显示分隔之后的第五列
awk -F: '{print $5}' /etc/passwd
//
定义多个分隔符,只要看到其中一个都 算作分隔符
awk -F[:/] '{print $1}' /etc/passwd
awk
常用内置变量:
$1
、
$2
、
NF
、
NR
、
$0
$1
:代表第一列
$2
:代表第二列以此类推
$0
:代表整行
NF
:一行的列数
NR
:行数
默认应该整行
多一个$0就多显示行内容
nr行数,可以不用print 直接默认显示
当然也可以加上效果一样
awk 'NR==2{print}' /etc/passwd //同上效果
打印第二行的第一列
awk -F: 'NR==2{print $1}' /etc/passwd
打印最后每行一列
awk -F: '{print $NF}' /etc/passwd
打印总行数
awk END'{print NR}' /etc/passwd
打印文件最后一行
扩展生产案列:网卡的ip、流量
查看流量
查看ip地址
查看磁盘空间
2.3、BEGIN 和 END 运算
逐行执行开始之前执行什么任务,结束之后再执行什么任务,用
BEGIN
、
END ,BEGIN一般用来做初始化操作,仅在读取数据记录之前执行一次
END
一般用来做汇总操作,仅在读取完数据记录之后执行一次。
小数也可以运算,不指定初始值,初始值就为0,如果是字符串,则默认为空。^和**都是幂运算,
BEGIN
在处理文件之前,所以后面不跟 文件名也不影响。
模糊匹配,用
~
表示包含,
!~
表示不包含
awk -F: '$1~/ro/' /etc/passwd //
模糊匹配,只要有
ro
就匹配上
awk -F: '$7!~/nologin$/{print $1,$7}' /etc/passwd
关于数值与字符串的比较
比较符号:
== != <= >= < >
第五行
和5行内
加“”代表精确查找
3到100列的
逻辑运算
&& ||
&&
和
||
是逻辑运算符,用于组合多个条件并控制程序流程。
&&
要求所有条件都为真时才为真,否则为假。
||
只要有一个条件为真就为真,全为假时才为假。
打印
1-200
之间所有能被
7
整除并且包含数字
7
的整数数字
其他内置变量的用法
FS
(输入)、
OFS
、
NR
、
FNR
、
RS
、
ORS
FS
:输入字段的分隔符 默认是空格
OFS
:输出字段的分隔符 默认也是空格
FNR
:读取文件的记录数(行号),从
1
开始,新的文件重新重
1
开始计数
RS
:输入行分隔符
默认为换行符
ORS
:输出行分隔符
默认也是为换行符
OFS的作用
OFS
定义了输出时以什么分隔,
$1 $2
中间要用逗号分隔,因为逗号默认被映射为
OFS
变量,而这个变量默认是空格
OFS
:输出分隔符 默认也是空格,我们这里是---,然后输出$2
awk 'BEGIN{FS=":";OFS="---"}{print $1,$2}' /etc/passwd
FNR
awk '{print FNR,$0}' /etc/resolv.conf /etc/hosts
可以看出 FNR的行号在追加当有多个文件时
NR
awk '{print NR,$0}' /etc/resolv.conf /etc/hosts
NR
代表当前记录号(即当前行号,在整个输入文件中是唯一的)。$0
代表当前记录的内容,即当前行的全部文本。
因此,'{print NR,$0}'
这个动作的意思是“打印当前行号(NR
)和当前行的全部内容($0
)”。
FNR区分文件给行号,NR不区分
RS
指定以什么为换行符,这里指定是冒号,指定的肯定是原文里存在的字符
ORS
把多行合并成一行 输出,输出的时候自定义以空格分隔每行,本来默认的是回车键
2.4、awk高级用法
定义引用变量
将系统的变量
a(提前有值为10)
,在
awk
里赋值为变量
b
,然后调用变量
b -v
选项将其传递给
awk
awk 'BEGIN{print "'$a'"}'
直接调用的话需要先用双引号再用单引号,双单
awk
直接定义变量并引用
awk -vc=1 'BEGIN{print c}'
调用函数
getline
,读取一行数据的时候并不是得到当前行而是当前行的下一行
df -h |awk 'BEGIN{getline}/root/{print $0}'
显示偶数行,也是调用getline函数
seq 10 | awk '{print $0;getline}' //
显示奇数行
2.5、awk if语句
awk
的
if
语句也分为单分支、双分支和多分支
awk -F: '{if($3<10){print $0}}' /etc/passwd
第三列小于10的打印出来
awk -F: '{if($3<10){print $3}else{print $1}}' /etc/passwd
多了一个else输出
2.6、AWK 数组
P
awk
数组的下标除了可以使用数字,也可以使用字符串,字符串需要使用双引号
awk 'BEGIN{a["abc"]=10;a[1]=20;print a["abc"]}'
2.7、awk 循环
awk 'BEGIN{a[0];a[1]=20;a[2]=20;for(i in a){print i,a[i]}}'
使用
awk
统计
httpd
访问日志中每个客户端
IP
的出现次数
?
awk '{a[$1]+=1}END{for(i in a){print a[i]" "i}}' /var/log/httpd/access_log| sort -r
备注
:
定义数组,数组名称为
ip
,数字的下标为日志文件的第
1
列(也就是客户端的
IP
地址
)
,
++
的目的在于对客户端进行统计计数,客户端IP
出现一次计数器就加
1
。
END
中的指令在读取完文件后执行,通过循环将所有统 计信息输出,for
循环遍历的是数组名
ip
的下标。
可用
awk
来统计固定格式日志里的一些数据,如日志中出现过所有不同的
IP
awk
对文件进行流处理,每次读取一行。
$1
就是
IP
,
count[i]
++
是将
IP
作为一个数组的下标,并且使得统计这个IP
所对应的数组元素自增
1.END
后面的语句是打印结果,只执行一次。
awk '{i=$1;count[i]++}END{for(i in count)print(i,count[i])}' /var/log/httpd/access_log
试题
1.怎么提取版本号
1
.9.7
给你道面试题
ant-1.9.7.jar
ant-launcher-1.9.7.jar
antlr-2.7.7.jar
antlr-runtime-3.4.jar
aopalliance-1.0.jar
archaius-core-0.7.6.jar
asm-5.0.4.jar
aspectjweaver-1.9.5.jar
bcpkix-jdk15on-1.64.jar
bcprov-jdk15-1.46.jar
bcprov-jdk15on-1.64.jar
checker-compat-qual-2.5.5.jar
只用出来1.9.7
2.
需求
:1.txt
文件中的内容 帅选出第一列 第三列 并且打印为一行,同时需求两列内容相隔
2
个空格
zhangsan
20
江苏南京 汉族 内容 文件名称
1.txt
2.8、总结
- grep 和 egrep 文本过滤 (更适合单纯的查找或匹配文本)
- sed 流编辑器 实现编辑的(更适合编辑匹配到的文本)
- awk 文本报告生成器 实现格式化文本输出(更适合格式化文本,对文本进行较复杂格式处理)
BEGIN中的命令只执行一次