DrewJhung's Blog

awk基础用法(一)

awk简介

awk主要用于文本处理,并将处理后的结果生成报告。awk 语法与C, python, bash尤为相似(awk 在python, bash之前就已经存在了)。其名称来自它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母相连。比较经典的使用场景:应用日志分析。

awk命令

  • 最简单的输出命令:
1
awk '{print}' /etc/passwd

上述命令中, 将/etc/passwd作为输入文件,命令为’{print}’ 。当执行awk时, 它默认把每一行看做一个处理单元,根据命令参数及action(如何处理每行分块后的结果)对每一行按序处理, action中{print $0}等价于{print}都会打印出整行。

  • 按照特定分隔符, 将每行切分(可以认为将每行切分的内容装入一个数组中):
1
2
3
4
5
6
7
8
# 以:为分隔符, 只打印每行分隔出来的第一个分隔块(取得数组的第一个元素)
awk -F ":" '{print $1}' /etc/passwd
# 以:为分隔符, 只打印每行分隔出来的第三个分隔块(取得数组的第三个元素)
awk -F":" '{ print $1 $3 }' /etc/passwd
# 以:为分隔符, 打印每行分隔的第一个和第三个分隔块(取得数组中的第一个和第三个元素), 并且2者用空格隔开打印
awk -F ":" '{print $1 " " $3}' /etc/passwd
# 也可以用转义字符打印分隔
awk -F ":" '{print $1 "\t" $3}' /etc/passwd
  • 执行awk脚本:

一般简单的文件处理用命令行会很方便, 但是如果遇到复杂的文件处理, 可能需要很复杂的多行命令处理, 这时将复杂处理写到脚本,直接调用脚本即可。

1
2
# 执行脚本命令格式(以下示例myscript.awk脚本处理/etc/passwd输入文件)
awk -f myscript.awk /etc/passwd

myscript.awk脚本:

1
2
3
4
5
6
BEGIN{
FS = ":"
}
{
print $1 " " $7
}
  • 命令中的BEGIN 和 END块

一般,awk会对文件中的每一行执行代码块。有一种情况是使用awk处理文本之前,执行变量初始化, 这时就需要BEGIN 块。使用BEGIN块可以设置FS(域分隔符), OFS (输出分隔符)或者初始化其他全局变量。

初始化全局变量:

1
2
3
4
5
6
7
8
9
10
11
BEGIN{
count = 1
}
{
for(i = 0;i<NR;i++){
count += i;
}
END{
print "文件内容总行数: ", count
}
}
  • 在awk中的正则表达式

在awk中使用正则表达式,筛选符合正则的行,正则表达式使用斜杠/包起来:

1
2
3
4
5
6
7
8
# 筛选/etc/passwd中有root的行, 并输出
awk '/root/ {print }' /etc/passwd
# 筛选/etc/passwd 中有root的行, 以:为分隔符将每一行分组, 并输出每一行第7个分组数据
awk '/root/ {print $7}' /etc/passwd
# 也可以是比较复杂的正则
awk '/[0-9]+\.[0-9]*/ {print}' /etc/passwd
  • 比较表达式:
1
2
3
4
5
6
7
8
9
# 如果每行分组的第一个分块==root, 就打印输出整行,1、2为等价写法
1、awk -F: '{if("root" == $1) print}' /etc/passwd
2、awk -F: '"root" == $1 {print}' /etc/passwd
# 匹配比较表达式
1、awk -F: '"/root/" ~ $1 {print}' /etc/passwd
2、awk -F: '{if("/root/" ~ $1) print}' /etc/passwd
3、awk -F: '$1 ~ /root/ {print}' /etc/passwd
4、awk -F: '{if($1 ~ /root/) print}' /etc/passwd
  • 条件表达式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 不匹配/root/
{
if($1 !~ /root/) {
print $7
}
}
# 不匹配的等价写法
1、! /matchme/ {print }
2、
{
if($0 !~ /matchme/) {
print
}
}
  • awk内置变量:
  1. FS(Field Separators) 设置每行的分隔符:
1
FS="\t+"
  1. NF(Number of fields) 每行按特定分隔符分隔后,获取分隔块的数目,即数组大小:
1
NF == 3 { print "this particular record has three fields: " $0 }
  1. NR(Record Number)获取当前记录的行号:
1
(NR < 10 ) || (NR > 100) { print "We are on record number 1-9 or 101+" }

参考资料

awk简介

Linux awk命令