Linux之awk

Linux中有三种主要的文本处理工具,分别是grep,sed和awk,其中grep是文本过滤工具,sed是文本行编辑器,awk是报表生成器,今天我们主要来探讨awk。

awk有nawk,gawk等多种版本,现在默认linux系统下的awk是gawk,也就是我们常用的awk,而在linux系统中gawk本身就是awk的链接文件,所以下文所说awk均为gawk。

 

一.大致功能

awk是一种用于处理文本的编程语言工具,在很多方面类似于shell编程语言,它支持条件判断,数组,循环等各种编程语言中所有可以使用的功能,所以在一定程度上我们可以把awk称为一种脚本语言解释器,由于awk在处理文本的时候一次读取一行,并根据分隔符进行切片,所以awk可以对文本中的特定片段进行各种加工处理,例如计数,运算等

 

二.用法格式

awk有三种运行方式,分别是以下三种

1.脚本

awk [options] ‘program’ var=value file

2.程序文件

awk [options] -f programfile var=value file

3.命令行

awk [options] 'BEGIN{ action;… } pattern{ action;… } END{ action;… }' file

 

其中的[options]:

-F 指明输入时用到的字段分隔符

-v var=value: 自定义变量赋值

awk的前两种运行方式直接调用文件或脚本,不多做解释,以下重点讨论awk的命令行用法

awk的命令行用法中,其格式由[options],BEGIN,pattern和END组成,其中[options]主要用于定义分隔符和定义变量,BEGIN是第一步仅且只执行一次的动作可以不写,pattern部分决定定动作语句何时触发及触发事件,以及触发什么事件,END是最后一步仅且只执行一次的动作,也可不写。

 

三.awk工作原理

第一步:执行BEGIN{action;… }语句块中的语句

第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。

第三步:当读至输入流末尾时,执行END{action;…}语句块

 

BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中

END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块

pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块

 

awk执行时,由分隔符分隔的字段(域)标记$1,$2..$n称为域标识

$0为所有域,注意:和shell中变量$符含义不同

文件的每一行称为记录

省略action,则默认执行 print $0 的操作,也就是打印整个记录

 

四.变量

awk中变量分为内置变量和自定义变量,自定义变量顾名思义就是我们自己定义的变量,而内置变量则是awk为方便我们的使用为我们提前准备号的变量,在定义变量时,建议在[options]部分定义内置变量

内置变量:

FS:输入字段分隔符,默认为空白字符

 

OFS:输出字段分隔符,默认为空白字符

 

RS:输入记录分隔符,指定输入时的换行符,原换行符仍有效

 

ORS:输出记录分隔符,输出时用指定符号代替换行符

 

NF:字段数量

 

NR:行号

 

FNR:各文件分别计数,行号

 

FILENAME:当前文件名

 

ARGC:命令行参数的个数

 

ARGV:数组,保存的是命令行所给定的各参数

 

自定义变量:

awk中定义自定义变量时若在[options]部分则直接用-v var=value(-v a=123)这样的方式定义即可,若在program中定义,需用“;”隔开,由于当value为数值时可以直接定义但value为带空格的字符串时无法识别所以建议在定义变量时用引号将value引起

 

五.printf/print

print

print格式: print item1, item2, ...

要点:

(1) 逗号分隔符

(2) 输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式

(3) 如省略item,相当于print $0

示例:

awk ‘{print "hello,awk"}'

awk –F: ‘{print}' /etc/passwd

awk –F: ‘{print “wang”}’ /etc/passwd

 

printf

按照格式输出,书写时先写目标格式,再在后面补上内容

printf格式:printf “FORMAT”, item1, item2, ...

要点:

(1) 由于printf是格式化输出所以必须指定FORMAT

(2) 不会自动换行,需要显式给出换行控制符,\n

(3) FORMAT中需要分别为后面每个item指定格式符

格式符:与item一一对应

%c: 显示字符的ASCII码

%d, %i: 显示十进制整数

%e, %E:显示科学计数法数值

%f:显示为浮点数

%g, %G:以科学计数法或浮点形式显示数值

%s:显示字符串

%u:无符号整数

%%: 显示%自身

修饰符:

#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f 表示一个三位的一位小数的浮点数

-: 左对齐(默认右对齐) %-15s 表示这一部分左对齐并去字符宽度为15,不足则空格补齐

+:显示数值的正负符号 %+d

示例:

awk -F: ‘{printf "%s",$1}’ /etc/passwd

awk -F: ‘{printf "Username: %s\n",$1}’ /etc/passwd
awk -F: ‘{printf "Username: %-15s,UID:%d\n",$1,$3}’ /etc/passwd

 

六.操作符

awk中支持各种操作符

算术操作符:

x+y, x

-y, x*y, x/y, x^y, x%y

-x: 转换为负数

+x: 转换为数值

赋值操作符:

=, +=,

-=, *=, /=, %=, ^=

++, --

逻辑操作符:与&&,或||,非!

比较操作符:

==, !=, >, >=, <, <=

模式匹配符:

~:左边是否和右边匹配(!~:是否不匹配)其中右边要匹配的部分要用“”或者//括起来

awk–F: ‘$0 ~ /root/{print $1}’ /etc/passwd

awk ‘$0~“^root"' /etc/passwd

awk ‘$0 !~ /root/’ /etc/passwd

 

七.awk action

awk有以下几种常用action

(1) Expressions:算术,比较表达式等

(2) Control statements:if, while等

(3) Compound statements:组合语句

(4) input statements

(5) output statements:print等

由于其他的action在上面都有介绍所以这里主要讲述控制语句而组合语句则是多种action的组合

 1.控制语句if-else

if语句常用于对awk取得的某个字段进行条件判断

格式:if(condition1){statement1}else if(condition2){statement2}

else{statement3}

例如:

awk读取/etc/passwd 输出系统用户和普通用户

awk -F: ‘{if($3>=1000) {printf "Common user: %s\n",$1} else {printf

"root or Sysuser: %s\n",$1}}' /etc/passwd

2.控制语句while

while常用于对同行内多个字段逐一处理和对数组个元素逐一处理

格式:while(condition){statement;…}

例如:

awk读取/etc/grub2.cfg 输出以任意空格加linux16作为开头的行的所有字段的长度

其中length()是一个awk的内置函数

awk ‘/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i); i++}}’ /etc/grub2.cfg

3.控制语句for

for语句功能和while基本相同,同样可用于遍历数组

格式:for(variable assignment;condition;iteration process) {for-body}

例如:

for代替上面的while输出以任意空格加linux16作为开头的行的所有字段的长度

awk ‘/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg

4.控制语句break/continue/next

awk中的break和continue同shell脚本中的功能一样,break跳出当前层的循环,continue跳过本次循环直接进入下一次,当然可以在break和continue跟上数字以表示跳出的循环个数,默认为1.而next则是跳出awk本身的循环,即直接进入下一行的循环。

例如:

awk '{for (i=1;i<3;i++){if (i==2){break}else{print i}}}' /etc/passwd这个循环中break直接跳出当前的for循环直接进入下一行的循环,如果把break换成continue则是跳出本次循环,直接进入i=3时的循环然后才进入下一行的循环。如果把break换成next则是直接进入下一行的循环,由于这个awk语句中除了awk本身的循环只有一层循环所以在这条语句中break和next作用相同。

 

八.数组

awk中数组通常是以字符串为下标的,其余和shell脚本中的数组基本相同

awk的数组一般写在pattern中,以遍历整个文件,然后在END中通过循环输出我们的数组

例如:

计算/etc/passwd中各种默认shell的个数,其中默认shell是这个文件每行的第七个域,在pattern部分直接以默认shell为数组下表,在awk循环遍历整个文件时,每遇到一种shell就在line数组中创建一个对应的下标,并让这个下标对应的值加一,之后每遇到一次都加一,然后在END部分通过for循环遍历输出每个下标及其对应的值,也就是出现的次数

awk -F: ‘{line[$7]++}END{for(i in line){print i,line[i]}}' /etc/passwd

posted @ 2018-09-01 11:10  白蓝的橙  阅读(185)  评论(0编辑  收藏  举报