awk句法格式

Oct 16, 2017


介绍


awk是一种解释性语言, 它不同于编译型语言. 是由数据驱动运行的. 而编译型语言是由编译器编译为机器语言进而由机器执行.

使用awk可以完成对文本数据的检索, 统计, 格式化等功能.

以下内容是对GNU下的gawk文档学习过程中的一些知识的记录.


详情


作用介绍

awk可以根据处理程序(自定义的处理方式)对文本信息进行处理.

  • 这个处理方式由一个个的规则(rule)组成. 每个规则具有两个部分:条件(pattern)行为(action)组成. 每个规则可以省略其中任意一个部分, 但不能两个都省略.

如果条件被省略, 表示行为部分将对每一条记录进行处理. 如果行为被省略, 表示输出符合条件的记录内容.

  • 文本信息既可以通过在awk命令后面添加参数的方式实现, 也可以通过标准输入的方式实现(在命令后面不跟任何文件).

运行方式

根据如何调用处理程序, 可以通过两种方式运行awk.

  • 命令行一次性调用
awk 'program' input-data1 input-data2 ...

# 通过使用单引号的方式告诉shell, program是awk命令的一个完整的参数, 不需要shell对其中的内容进行解释或者转化.
# input-dataN 表示需要使用program处理的文本文件. 如果没有这个参数则表示文本文件来自于标准输入.
  • 使用source-file的方式调用
awk -f source-file input-data1 input-data2 ...

# source-file中写有awk的表达式, 内容和上面一种的program一致. 这不过这种方式常用于处理程序内容较多且会被重复使用的情况下.

引号注意事项

在命令行一次性调用方式下, 经常会出现下面的问题: 需要在执行程序(program)中使用单引号, 但是由于program有需要被单引号包括在中间, 所以此时需要对单引号进行特殊处理.

例如下面示例中的情况:

awk 'BEGIN { print "Don't Panic" }'

# 因为处理程序中没有规定对每一条记录的处理方式, 所以在BEGIN执行完成之后, awk不会读取文本文件中的内容进行处理, 所以这里可以不需要文本文件作为参数, 也不会从标准输入中获取文本内容.

这种情况下, 首先想到的是想到的是对单引号进行转义\', 但是在shell中并不会去刻意识别转义字符, shell仍然会按照单引号的方式处理输出内容.

为了解决上面的问题, 有两种方法刻意使用.

  • 双引号包含的处理程序中, 不会将单引号作为特殊字符进行处理. 和我们常用的其他脚本语言类型比如js. 所以:
awk "BEGIN { print \"Don't Panic\" }"
  • 使用字符串级联, 即字符串连接.

比如Java中使用+连接两个字符串, 如”Hello “+”World!”. 同样shell中也具有字符串级联的方式, 但与Java中略有不同的是两个字符串的级联不需要使用任何操作符, 即直接将两个字符串写在相邻位置即可. 例如: ‘hello ‘‘World’将得到’hello World’.

使用字符串的级联, 同时利用双引号中不将单引号作为特殊字符的特性可得:

awk 'BEGIN { print "Don'"'"'t Panic" }'

# 上面的示例中有三段字符串, 分别是:'BEGIN { print "Don', "'" 和 't Panic" }', 三个字符串通过级联的方式合为一个字符串.

注意: 两个级联的字符串不一定需要使用同样的引号方式, 即单引号字符串既可以级联单引号字符串又可以级联双引号字符串.

当然如果使用source-file方式运行awk, 不会出现类似的问题, 因为可以直接使用转义符号处理.

处理程序内容的分隔

以上介绍可得处理由多个规则组成, 为了区分这些规则中每个独立单元(如: 一个规则, 一个行为, 一个表达式等), 这里介绍一下awk程序是如何区分每个单元的.

  • 规则与规则之间

规则之间使用换行符区分, 即不同的行将被视为不同的规则

rule1
rule2
  • 条件和行为之间

同一个规则中的条件和行为之间不能使用换行符, 如果在条件与行为之间使用换行符则会将一个规则变为两个规则, 前一个规则中只包含一个条件, 后一个规则中只包含一个行为.

rule1 (条件 {行为})
rule2 (条件)
rule3 ({行为})

# 如果需要将一个规则中的条件和行为分为两行的话, 可以使用反斜线\来实现, \必须在行尾
rulen (条件 \
{行为})
  • 行为中的每个语句

语句与语句之间使用换行符分隔, 如果需要在同一行写两条语句的话, 需要在第一个语句后面使用分号;作为分隔符.

{
	语句1
	语句2
	语句3; 语句4

	# 如果一条语句过长, 需要使用两行来表示, 也可以使用反斜线在行尾的方式实现.
	语\
	句n #语句n是分为两行写出来的一个语句
}

注意: 如果在行尾出现逗号,, 左大括号{, 三目运算符? :, ||, &&, do, else这些关键字时我们将这行数据和下一行数据视为同一行数据.


参考文件



上一篇博客:awk的printf函数中格式化控制字符的含义
下一篇博客:awk学习-第二章-awk和gawk的运行