awk既是一个shell工具,也是一门编程语言,linux和osx下都可以直接用,windows下有gawk(下载链接)。
以下内容参考mawk用户手册(man awk
),可能与标准awk语言有出入
一、工作原理
- awk扫描输入的每一行(记录分隔符
RS
, record separator), - 每行会被分隔成若干个域(域分隔符
FS
, field separator), - 根据
pattern
匹配每一行, - 如果匹配就执行
action
二、awk解释器
程序文件
- 短的程序内容可以用单引号包括,直接在命令行中运行;
awk '{print $1}' text_file
- 长的程序文件可以通过
-f
参数指定路径。
awk -f awk_program_file text_file
文本文件
- awk可以接收多个文件路径作为输入
- awk可以接收管道输出作为输入
- 如果没有指定上面两者,awk对标准输出进行处理
mawk命令行
mawk [-W option] [-F value] [-v var=value] [--] 'program text' [file ...]
mawk [-W option] [-F value] [-v var=value] [-f program-file] [--] [file ...]
三、awk编程语言
1). 程序结构
awk程序包含若干pattern {action}
序列和函数定义。
-
pattern
和action
不能同时省略
-
pattern
可以省略,如果省略,默认匹配成功 -
action
可以省略,如果省略,默认为print
-
pattern
可以为
-
BEGIN
匹配文本文件开始位置, 其action
不能为空 -
END
匹配文本文件结束位置,其action
不能为空 -
expression
单个表达式 -
expression, expression
多个表达式
- 其他语句
- 语句结束符为新行或者分号;
- 一个语句块由大括号包围;
- 一条语句可以使用反斜杠进行跨行;
- 注释由
#
开头
- 流程控制语句
if ( expr ) statement
if ( expr ) statement else statement
while ( expr ) statement
do statement while ( expr )
for ( opt_expr ; opt_expr ; opt_expr ) statement
for ( var in array ) statement
continue
break
2). 数据类型
awk有两种基本数据类型:
- 数字型
- 可以为整数
2, -2
- 可以为小数
0.5
- 可以为科学表示法数字
0.2e8 1.2E5
所有数字内部由浮点数进行表示和计算,
true
表示为1.0
- 字符型
- 字符串用双引号包括
"a string"
- 特殊字符可以由反斜杠\转义
3). 正则表达式
正则表达式由斜杠包括/r/
;
- 匹配操作符
~
右侧可以为一个表达式 - 非匹配操作符
!~
右侧可以为一个表达式
pattern-action对可以这样表示:
/r/ {action}
或$0 ~ /r/ {action}
4). 记录和域
- 每次记录(record, 行)存储在域(field)
$0
中, - 每行被分隔为多个域,分别存在
$1, $2, ... $NF
中, -
NF
(number of fields)被设置为域的数量, -
NR
和FNR
递增
5). 表达式和操作符
基本表达式
- 数字常量
- 字符串常量
- 变量
- 域
- 数组
- 函数调用
变量、数组和函数命名可以为字符、数字、下划线,不能以数字开头。
变量不用声明,第一次使用会被初始化为null
操作符:
assignment = += -= *= /= %= ^=
conditional ? :
logical or ||
logical and &&
array membership in
matching ~ !~
relational < > <= >= == !=
concatenation (no explicit operator)
add ops + -
mul ops * / %
unary + -
logical not !
exponentiation ^
inc and dec ++ -- (both post and pre)
field $
6). 数组
awk可以表示一维数组array[expr]
, expr
会被转换为字符串类型。
- 成员检查
expr in array
在返回1
,否则返回0
- 下标遍历
for(var in array)
- 删除成员
delete array[expr]
- 多维数组
array[expr1, expr2]
等于array[expr1 SUBSEP expr2]
- 成员测试
if( (i, j) in array) print array[i, j]
- 成员测试
7). 内建变量
变量名 | 含义 | 缩写 |
---|---|---|
ARGC |
参数数量 | |
ARGV |
参数数组 | |
CONVFMT |
内部数字转字符串格式,默认为%.6g
|
|
ENVIRON |
环境变量数组 | |
FILENAME |
当前输入文件 | |
FNR |
当前记录编号 | file record number |
FS |
域分隔符 | field separator |
NF |
域数量 | number of fields |
NR |
当前记录编号 | record number |
OFMT |
数字输出格式, 默认%.6g
|
output format |
OFS |
输出域分隔符,默认空格 | output field separator |
ORS |
输出记录分隔符 默认\n
|
output record separator |
RLENGTH |
最近一次match调用的长度 | |
RSTART |
最近一次match调用得到的下标 | |
RS |
输入记录分隔符 | record separator |
SUBSEP |
多维数组下标分隔符,默认\034
|
subscript separator |
8). 内建函数
字符串函数 | 含义 | 算术函数 | 含义 |
---|---|---|---|
gsub(r, s[, t]) |
字符串替换 | atan2(y, x) |
|
index(s, t) |
返回子串位置 | cos(x) |
|
length(s) |
返回字符串长度 | exp(x) |
|
match(s, r) |
返回首个匹配位置 | int(x) |
取整 |
split(s, A[, r]) |
分隔s到A数组 | log(x) |
|
sprintf(format, expr-list) |
rand() |
0-1之间随机数 | |
sub(r, s[, t]) |
替换一次 | sin(x) |
|
substr(s, i[, n]) |
返回子串 | sqrt(x) |
|
tolower(s) |
返回小写形式 | srand([expr]) |
根据种子随机 |
toupper(s) |
返回大写形式 |
9). 输入输出
输出语句:
print
print expr1, expr2, ..., exprn
printf format, expr-list
输入语句:
-
getline
读取一行 -
getline < file
从文件读取一行 -
getline var
读到var -
getline var < file
从文件读到var -
command | getline
从管道读取一行 -
command | getline var
从管道读到var
其他语句:
-
close(expr)
关闭文件 -
fflush(expr)
刷新输出文件 -
system(expr)
执行expr
10). 自定义函数
格式:
function name(args) { statements }
可以有返回值,但不必须:
return opt_expr
传入参数和局部变量参数之间使用多个空格分隔(惯例)
11). 字符串、记录、文件分隔
同一种分隔算法:split(expr, A, sep)
12). 多行记录
设置RS
13). 程序执行
-
ARGC
被设置为命令行参数数目,ARGV[0]
被设置为awk解释器,ARGV[i]
被设置为其余命令行参数 - 然后
BEGIN
语句块被依次执行。如果只有BEGIN
语句,程序结束;否则打开输入流。如果ARGC
=1,输入流被设置为stdin
。然后ARGV[i]
将被作为文件参数检查。 - 命令行参数可分为三类:文件参数、赋值参数、空字符串。赋值参数格式为
var=string
。如果ARGV[i]
可能是个文件参数,如果为空就跳过;如果是赋值参数,就会设置var的值,然后跳到下个参数;否则ARGV[i]
作为输入打开。如果打开失败,程序结束,返回错误码2。如果没有参数是文件参数,输入从stdin
获取。在BEGIN
中getline
会打开输入,-
表示stdin
。 - 输入流打开之后,每条输入记录都会与
pattern
进行匹配。如果匹配,相关的action
就会执行。表达式模式为true
时才匹配。BEGIN
匹配在任何输入读取之前匹配,END
在所有输入读取结束之后匹配。范围表达式expr1, expr2
匹配两个表达式分别匹配的行之间所有行,并包含这两个匹配行。 - 当输入流的文件结束时,其余的命令行参数会被检查是否是文件参数,如果有就会被打开,重复上一步骤。如果没有,
END
模式会被匹配,所有的END
的action
都会被执行。 -
pattern {action}
层次的程序流程可以被一下语句改变:next
exit opt_expr
其他参考
酷壳
man awk