7.6 awk使用与实战
sed命令应用与实战
Linxu 上有文本处理三剑客grep
,sed
,awk
。本节我们来学习最后一个命令 awk 的使用。
awk 算得上是一门编程语言,这个编程语言内有包括变量,条件判断,循环,命令等诸多语言特性。我们将按照类似 bash 脚本的方式,从变量开始逐一讲解 awk 的使用。内容概述如下:
- awk 命令简介
- awk 变量与数组的使用
- awk 程序执行逻辑,包括顺序执行,条件判断和循环
- awk 内置函数
有关 awk 的使用推荐大家阅读
- 《sed和awk》
- 《Linux Shell与脚本编程指南》
1. awk 简介
Centos 中的 awk 是 GNU awk即 gawk。awk 是指向 gawk 命令的软连接
|
|
1.1 awk 处理逻辑
如上图,awk 将文件处理分成三个阶段。第一阶段由 BEGIN 标识,第三阶段由 END标志,分别位于文件处理前和文件处理之后。
文本处理位于第二阶段,awk 每次读取文件中的一行,按照内部 FS 变量标识的分割符,将行分割成多个字段。字段按照位置分别保存在 $1
,$2
,$3
…. 等变量中,供 awk 编程使用,$0
表示整行。awk 中的字段变量如下所示
|
|
作为一个编程语言,awk 有一些基本的语法特性,如果你有其他编程语言的使用经验,记住这些语法特性基本上很快就能写出 awk 程序。我们以如下例子来说明这些基本特性
awk -F: '/^r/{if ($3$10) {i=1;printf "|%-15s |%-15s|\n",$1,$7} }' /etc/passwd
- 使用
{}
分割代码块 - 控制语句的条件判断放置在
()
内 - 代码块内的多条语句使用
;
分割,按顺序从左往右执行 - 使用
""
表示字符串 - 使用
/pattern/
表示使用正则表达式
如果你不懂上面说的什么意思,没有关系,我们接下来会详细介绍 awk 的语法。
1.2 awk 命令使用
gawk [options] 'program' FILE ...
- 作用: 文件格式化工具
- 选项:
-F
:指明输入时用到的字段分隔符;-v var=value
: 自定义变量;
- 参数:
FILE
: 待处理的文本文件,可多个program
: awk 编程脚本,必须使用单引号括起- 格式:
'PATTERN{ACTION STATEMENTS}'
PATTERN
:过滤出要处理的行{ACTION STATEMENTS}
: 编程语句表达式
- 格式:
|
|
1.3 PATTERN
PATTERN 用于过滤出要处理的行,有如下几种过滤方式
empty
:- 作用: 空模式,匹配每一行
/regular expression/
- 作用: 仅处理能够被此处的模式匹配到的行;
relational expression
:- 作用: 关系表达式;结果为“真”才会被处理;非0值,非空均为真;
/pat1/,/pat2/
:- 作用: 从 pat1 匹配首行到 pat2 匹配的首行之间的行
- 注意: 不支持类似 sed 直接给出数字的格式
startline,endline
,只能通过关系表达式实现
BEGIN/END
模式BEGIN{}
: 仅在开始处理文件中的文本之前执行一次;END{}
:仅在文本处理完成之后执行一次;
pattern 使用示例
下面是一些使用 PATTERN 的示例,可以先跳过。
|
|
2. awk 编程语法
2.1 变量
变量特性
awk 中变量具有如下特性:
- 区分大小的
- 变量直接引用,无需使用
$
,$1
整体表示一个变量,存储了第一个字段的值 - 自定义变量可以通过
-v var=value
选项指定,也可以在program中直接定义
|
|
内置变量
awk 有众多内置变量,常见的如下所示:
FS
:input field seperator,默认为空白字符;OFS
:output field seperator,默认为空白字符;RS
:input record seperator,输入时的换行符;ORS
:output record seperator,输出时的换行符;-NF
:number of field,字段数量{print NF}
: 打印当前行列数{print $NF}
: 打印当前行最后一个字段的值
NR
:number of record, 行数;如果 awk 后跟多个文件,这个NR
将是所有行的累计值FNR
:各文件分别计数;行数;FILENAME
:当前文件名;ARGC
:命令行参数的个数;ARGV
:数组,保存的是命令行所给定的各参数;
2.2 输出
awk 的输出有 print
,printf
两个命令
print item1, item2, ...
- 作用: 输出后跟的内容
- 特性:
- 逗号分隔符;
- 输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式;
- 如省略item,相当于
print $0
;
printf
printf FORMAT, item1, item2, ...
- 作用: 格式化输出,与 C 语言的 printf 函数的使用方式完全相同,bash中也有同名命令
- 说明: printf 不会自动换行,需要显式给出换行控制符,
\n
- 参数:
- FORMAT: 格式化字符串,表示以特定格式显示数据;包括格式符和修饰符两个部分
- item1..: 被格式化的数据,FORMAT中需要分别为后面的每个item指定一个格式化符号;
- 格式符:
%c
: 显示字符的ASCII码;%d, %i
: 显示十进制整数;%e, %E
: 科学计数法数值显示;%f
: 显示为浮点数;%g, %G
:以科学计数法或浮点形式显示数值;%s
:显示字符串;%u
:无符号整数;%%
: 显示%自身;
- 修饰符:
#[.#]
:第一个数字控制显示的宽度;第二个数字表示小数点后的精度-
: 左对齐+
:显示数值的符号
|
|
2.3 操作符
awk 支持几乎所有的常规操作符
- 算术操作符:
x+y, x-y, x*y, x/y, x^y, x%y
-x
+x
: 转换为数值;
- 字符串操作符:没有符号的操作符,字符串连
- 赋值操作符:
=, +=, -=, \*=, /=, %=, ^=
++, --
- 比较操作符:
$, $=, <, <=, !=, ==
- 模式匹配符:后接正则表达
~
:是否匹配!~
:是否不匹配
- 逻辑操作符:
&&
||
!
- 条件表达式:
selector?if-true-expression:if-false-expression
|
|
2.4 控制语句
过程式编程语言的代码执行顺序有顺序执行,条件判断和循环。awk 中常见的控制语句语法如下所示:
if(condition) {statments}
if(condition) {statments} else {statements}
while(conditon) {statments}
do {statements} while(condition)
for(expr1;expr2;expr3) {statements}
break
continue
next
代码块使用 {}
,控制语句中的条件放置在 ()
内,而 代码块内顺序执行的代码使用 ;
分隔。
if-else
if(condition) statement [else statement]
|
|
while循环
while(condition) statement
- 使用场景:对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用;
|
|
do-while循环
do statement while(condition)
- 意义:至少执行一次循环体
for循环
for(expr1;expr2;expr3) statement
: 普通 for 循环for(var in array) {for-body
:遍历数组的特殊语法格式
|
|
switch语句
switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement}
next
awk 内自动按行进行遍历,awk 内的循环主要用来遍历每行内的所有字段,next 是 awk 特有的,用来提前结束 awk 内对本行的处理而直接进入下一行;
|
|
2.5 关联数组
array[index-expression]
index-expression
:- 可使用任意字符串;字符串要使用双引号;
- 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”,如果用于数值运算,默认为 0;
- 若要判断数组中是否存在某元素,要使用
index in array
格式进行; - 若要遍历数组中的每个元素,要使用for循环,注意 for 循环迭代的是下标不是值;
for(var in array) {for-body}
|
|
2.6 函数
函数调用使用 function_name(argu1, argu2, ...)
内置函数
- 数值处理:
rand()
:返回0和1之间一个随机数;
- 字符串处理:
length([s])
:返回指定字符串的长度;sub(r,s,[t])
:以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;gsub(r,s,[t])
:以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现均替换为s所表示的内容;split(s,a[,r])
:以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中;
|
|