Linux中有三种主要的文本处理工具,分别是grep,sed和awk,其中grep是文本过滤工具,sed是文本行编辑器,awk是报表生成器,今天咱们主要来探讨awk。linux
awk有nawk,gawk等多种版本,如今默认linux系统下的awk是gawk,也就是咱们经常使用的awk,而在linux系统中gawk自己就是awk的连接文件,因此下文所说awk均为gawk。shell
awk是一种用于处理文本的编程语言工具,在不少方面相似于shell编程语言,它支持条件判断,数组,循环等各类编程语言中全部可使用的功能,因此在必定程度上咱们能够把awk称为一种脚本语言解释器,因为awk在处理文本的时候一次读取一行,并根据分隔符进行切片,因此awk能够对文本中的特定片断进行各类加工处理,例如计数,运算等编程
awk有三种运行方式,分别是如下三种数组
1.脚本编程语言
awk [options] ‘program’ var=value file编辑器
2.程序文件函数
awk [options] -f programfile var=value file工具
3.命令行spa
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是最后一步仅且只执行一次的动做,也可不写。
第一步:执行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引发
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 “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
(1) Expressions:算术,比较表达式等
(2) Control statements:if, while等
(3) Compound statements:组合语句
(4) input statements
(5) output statements:print等
因为其余的action在上面都有介绍因此这里主要讲述控制语句而组合语句则是多种action的组合
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
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
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
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