文本处理-awk

awk既是一个shell工具,也是一门编程语言,linux和osx下都可以直接用,windows下有gawk(下载链接)。

以下内容参考mawk用户手册(man awk),可能与标准awk语言有出入

一、工作原理

  1. awk扫描输入的每一行(记录分隔符RS, record separator),
  2. 每行会被分隔成若干个域(域分隔符FS, field separator),
  3. 根据pattern匹配每一行,
  4. 如果匹配就执行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}序列函数定义

  1. patternaction不能同时省略
  • pattern可以省略,如果省略,默认匹配成功
  • action可以省略,如果省略,默认为print
  1. pattern可以为
  • BEGIN 匹配文本文件开始位置, 其action不能为空
  • END 匹配文本文件结束位置,其action不能为空
  • expression 单个表达式
  • expression, expression 多个表达式
  1. 其他语句
  • 语句结束符为新行或者分号;
  • 一个语句块由大括号包围;
  • 一条语句可以使用反斜杠进行跨行;
  • 注释由#开头
  1. 流程控制语句
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有两种基本数据类型:

  1. 数字型
  • 可以为整数 2, -2
  • 可以为小数 0.5
  • 可以为科学表示法数字 0.2e8 1.2E5

所有数字内部由浮点数进行表示和计算,true表示为1.0

  1. 字符型
  • 字符串用双引号包括 "a string"
  • 特殊字符可以由反斜杠\转义

3). 正则表达式

正则表达式由斜杠包括/r/

  • 匹配操作符~ 右侧可以为一个表达式
  • 非匹配操作符!~ 右侧可以为一个表达式
    pattern-action对可以这样表示:
    /r/ {action}$0 ~ /r/ {action}

4). 记录和域

  • 每次记录(record, 行)存储在域(field)$0中,
  • 每行被分隔为多个域,分别存在$1, $2, ... $NF中,
  • NF(number of fields)被设置为域的数量,
  • NRFNR递增

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获取。在BEGINgetline会打开输入,-表示stdin
  • 输入流打开之后,每条输入记录都会与pattern进行匹配。如果匹配,相关的action就会执行。表达式模式为true时才匹配。BEGIN匹配在任何输入读取之前匹配,END在所有输入读取结束之后匹配。范围表达式expr1, expr2匹配两个表达式分别匹配的行之间所有行,并包含这两个匹配行。
  • 当输入流的文件结束时,其余的命令行参数会被检查是否是文件参数,如果有就会被打开,重复上一步骤。如果没有,END模式会被匹配,所有的ENDaction都会被执行。
  • pattern {action}层次的程序流程可以被一下语句改变:
    • next
    • exit opt_expr

其他参考

酷壳
man awk

你可能感兴趣的:(文本处理-awk)