awk 使用示例

awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。

awk 脚本基本结构

awk 'BEGIN{ commands } pattern{ commands } END{ commands }'

一个awk脚本通常由:BEGIN语句块能够使用模式匹配的通用语句块END语句块 3部分组成,这三个部分是可选的。任意一个部分都可以不出现在脚本中,脚本通常是被放置在 单引号

awk 的工作原理

  1. 执行 BEGIN{ commands } 语句块中的语句;
  2. 从文件或标准输入(stdin)读取一行,然后执行 pattern{ commands } 语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
  3. 当读至输入流末尾时,执行 END{ commands } 语句块。

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

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

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

awk 内置变量(预定义变量)

变量 说明 示例
$0 当前行的整行内容 '{print $0}' 打印出当前处理行的整行内容
$n 当前记录(行)的第n个字段 '{print $1}' 打印出当前行的第1个字段
NR 当前处理行的行号(第多少行) '{print NR,$1}' END{print NR} 打印出当前处理行的行号和第1列,最后打印出总的行号
FNR 当前处理行在当前处理文件中的行号,只有1个输入文件时,NR=FNR
NF 当前行的字段数 '{print NF,$NF,$(NF-1)}' 输出当前行的字段数,最后一个字段 ,倒数第2个字段
FILENAME 当前输入文件的文件名,-表示stdin '{print FILENAME,FNR}' 打印当前处理的文件名及当前行号
FS 输入字段分隔符,等同于选项 -F ,默认为空格
OFS 输出字段的分隔符,默认为空格 'BEGIN{OFS="|"} {print FILENAME,FS,NR,NF,$2,$NF}' 输出结果将会以 | 分割
RS 输入记录分隔符(行分隔符),默认为换行
ORS 输出记录分隔符(行分隔符),默认为换行

awk 常用选项

选项 说明 示例
-F"sep"
-F"[,.]"
等同于内置变量 FS,有2种格式:
-F"sep" 使用 sep 整体作为字段分隔符
-F[,.] []其中的每个字符都可以作为分隔符
等同于BEGIN预定义变量FS
-v var=1 传递用户自定义变量给awk awk -va=1 -vb=2 '{print a+b}'

awk 常用运算符

运算符 说明 示例
=
+=
-=
*=
/=
%=
^=
**=
赋值
~
!~
匹配正则表达式
不匹配正则表达式
awk '$2 ~ /th/ {print $2,$4}' log.txt 第2列中包含’th’,则输出第2,4列
awk 'BEGIN{IGNORECASE=1} /this/' log.txt 忽略大小写匹配
awk '$2 !~ /th/ {print $2,$4}' log.txt 不匹配正则表达式
<
<=
>
>=
!=
==
关系运算符 awk '$1>2' log.txt 第1列的值大于2,输出整行
awk '$1==2 {print $1,$3}' log.txt 第1列的值等于2,则输出第1,3列
+
-
*
/
%
加,减,乘,除与求余
+
-
!
一元加,减和逻辑非
| | 逻辑或
&& 逻辑与 awk '$1>2 && $2=="Are" {print $1,$2,$3}' log.txt 第1列大于2,并且第2列等于”Are”,则输出第1,2,3列

awk 常用用法示例

每一行中第个字段值累加

awk
seq 1 10 | awk 'BEGIN{sum=0;print "第1列求和"}{sum+=$1}END{print "sum="sum}'

第1列求和
sum=55

判断2列的内容是否相同

awk
awk '{if($1==$2){print $1}}'

找出字段数(列数)大于3的行

awk 'NF>3{print $0}' 

参考链接

参考文章