介绍
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
这些关键字时我们将这行数据和下一行数据视为同一行数据.