awk指令

awk指令介绍:

  • AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。

  • 通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。

  • 之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

  • awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。

流程简介

如图所示,共分为读取文件前读取文件读取文件后三个阶段

基本介绍

  • 语句的格式为:awk 参数 '条件{动作}' 文件路径,条件和动作标准的叫法是'pattern{action}',即模式和行为
  • 若不加条件则对每一行都生效,若不加动作则默认显示这一行
  • 默认以回车分隔每一行,以空格(或tab)分隔每一列
  • -F,表示以,分隔每一列,如果分隔符不止一种,需要使用正则表达式
  • 命令行参数之后的内容用''
  • 字符串用""

示例:

  1. ls -l | awk '{print $5}' :只有动作而无条件,意思是打印每一行的第五列
  1. 基本同上,输出每一行的第五列和第九列。顺带一提,$NF表示最后一列

    column -t可以格式化输出结果

  1. 对以上规则的综合运用,添加BEGIN和END

行与列

行也称作记录,列也称作字段、域

取行

  • NR==1:取出第一行
  • NR>=1&&NR<=5:取出1到5行
  • /oldboy/:传入正则表达式,得到匹配的行

取列

  • $数字:取出某一列
  • $0:整行的内容
  • $NF:最后一列

实战:

-F"[ /]"表示分隔符为空格或斜杠,对于第三行,第一个元素为空格,第二个元素为inet,第三个元素为10.0.0.61

内建变量

来自菜鸟教程,供参考:

变量 描述
$n 当前记录的第n个字段,字段间由FS分隔
$0 完整的输入记录
ARGC 命令行参数的数目
ARGIND 命令行中当前文件的位置(从0开始算)
ARGV 包含命令行参数的数组
CONVFMT 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
ERRNO 最后一个系统错误的描述
FIELDWIDTHS 字段宽度列表(用空格键分隔)
FILENAME 当前文件名
FNR 各文件分别计数的行号
FS 字段分隔符(默认是任何空格)
IGNORECASE 如果为真,则进行忽略大小写的匹配
NF 一条记录的字段(列)的数目
NR 已经读出的记录数,就是行号,从1开始
OFMT 数字的输出格式(默认值是%.6g)
OFS 输出字段分隔符,默认值与输入字段分隔符一致。
ORS 输出记录分隔符(默认值是一个换行符)
RLENGTH 由match函数所匹配的字符串的长度
RS 记录分隔符(默认是一个换行符)
RSTART 由match函数所匹配的字符串的第一个位置
SUBSEP 数组下标分隔符(默认值是/034)

模式匹配

比较表达式

参考上方内容

正则

awk可以精确到某一列,通过某一列包含/不包含…内容来进行筛选,其中~表示包含,!~表示不包含

正则 awk正则
^ 某一列的开头 $3~/^oldboy/
$ 某一列的结尾 $4~/oldboy$​/
^$ 空行 某一列是空的

实例:/etc/passwd文件中,以:分隔行,找出第三列以1或2开头的行,打印出该行的第一、三和最后一列

以下三种写法等价,推荐第一种:

1
2
3
awk -F: '$3~/^[12]/{print $1,$3,$NF}' /etc/passwd
awk -F: '$3~/^1|^2/{print $1,$3,$NF}' /etc/passwd
awk -F: '$3~/^(1|2)/{print $1,$3,$NF}' /etc/passwd

表示范围

  • /开始/,/结束/:较常用,要匹配文本的内容,见示例
  • NR==1,NR==5:从第一行到第五行结束
1
2
3
# 显示指定时间(11:02:00~11:02:30)范围内容的ip地址

awk '/11:02:00/,/11:02:30/{print $1}' access.log

由于每一条日志里都有时间的字段,awk就可以匹配这些时间,列出该时间范围内的日志

特殊模式

模式 含义 场景
BEGIN{} 里面的内容会在awk读取文件之前执行 进行简单统计、计算,不涉及读取文件
END{} 里面的内容会在awk读取文件之后执行 1) awk进行统计,一般过程:先进行计算,最后在END里面输出结果 2) awk使用数组,用来输出数组结果

END统计方法(i和sum都是变量):

统计方法 简写形式 场景
i=i+1 i++ 计数,统计次数
sum=sum+??? sum+=??? 求和,累加

示例:

  1. 统计空行的个数:
1
2
3
4
# 方法一:使用 wc -l 管道命令
awk '/^$/' /etc/services |wc -l
# 方法二:使用特殊模式
awk '/^$/{i++}END{print i}' /etc/services
  1. 求和:
1
2
3
seq 100 | awk '{sum+=$1}END{print sum}' # 5050
# 如果要体现出计算过程:
seq 100 | awk '{sum+=$1;print sum}END{print sum}'

补充:wc指令

Linux wc命令用于计算字数。
利用wc指令我们可以计算文件的Byte数、字数、或是列数,若不指定文件名称、或是所给予的文件名为”-“,则wc指令会从标准输入设备读取数据。

语法:wc [-clw][--help][--version][文件...]

参数:

  • -c或–bytes或–chars 只显示Bytes数。
  • -l或–lines 显示行数。
  • -w或–words 只显示字数。
  • –help 在线帮助。
  • –version 显示版本信息。

在默认的情况下(不加选项),wc将计算指定文件的行数、字数,以及字节数

awk数组

用途:

  • 统计次数:统计每个ip出现次数,统计每种状态码出现次数,统计系统中每个用户被攻击的次数,统计攻击者ip出现次数
  • 累加求和:统计每个ip消耗的流量
shell数组 awk数组
形式 array[0]=oldboy array[0]=oldboy
使用 echo ${array[0]} print array[0]
批量输出数组内容 for i in ${array[*]}
do
echo ${array[i]}
done
for(i in array)
print array[i]

示例:

1
2
3
awk 'BEGIN{a[0]=12345;a[1]="danmo"; for(i in a) print a[i]}'
# 12345
# danmo

演示统计功能:

假设这是一个log内的信息:

awk数组可以进行分类统计,在此例中,则是统计每个顶级域名出现的次数

补充:sort指令

Linux sort 命令用于将文本文件内容加以排序。
sort 可针对文本文件的内容,以行为单位来排序。

语法:

1
sort [-bcdfimMnr][-o<输出文件>][-t<分隔字符>][+<起始栏位>-<结束栏位>][文件][-k field1[,field2]]
  • -b 忽略每行前面开始出的空格字符。
  • -c 检查文件是否已经按照顺序排序。
  • -d 排序时,处理英文字母、数字及空格字符外,忽略其他的字符。
  • -f 排序时,将小写字母视为大写字母。
  • -i 排序时,除了040至176之间的ASCII字符外,忽略其他的字符。
  • -m 将几个排序好的文件进行合并。
  • -M 将前面3个字母依照月份的缩写进行排序。
  • -n 依照数值的大小排序。
  • -u 意味着是唯一的(unique),输出的结果是去完重了的。
  • -o<输出文件> 将排序后的结果存入指定的文件。
  • -r 以相反的顺序来排序。
  • -t<分隔字符> 指定排序时所用的栏位分隔字符。
  • +<起始栏位>-<结束栏位> 以指定的栏位来排序,范围由起始栏位到结束栏位的前一栏位。
  • [-k field1[,field2]] 按指定的列进行排序。

sort排序是不改变源文件的,可以-o <输出文件>来将修改后的内容存入一个新的文件

流程控制

for

示例:

1
2
awk 'BEGIN{for(i=1;i<=100;i++){sum+=1} print sum}'
# 5050

if

示例:

查找占用容量超过1%的行,显示其第1、5和最后一列

面试题:输出长度小于6的列(字段):