前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >awk学习笔记

awk学习笔记

作者头像
小小科
发布2018-05-02 17:26:14
1.8K0
发布2018-05-02 17:26:14
举报
文章被收录于专栏:北京马哥教育北京马哥教育

awk是一种模式扫描和处理工具,相对于grep的查找,sed的编辑,它在对数据进行分析生成报表时显得尤为强大。awk通过逐行遍历一个或多个 文件的方式,查找模式匹配到的行,而后以指定的分隔符(缺省为空格)进行切片,然后针对切片数据进行处理和分析。事实上,gawk有自己的语言,其本身就 相当于一个解释器,允许用户创建简短的程序读取输入文件,对输入数据执行排序、计算以及生成报表操作,甚至可以类似bash shell实现诸如循环、数组、条件判断、函数、变量等功能,进而完成更为复杂的数据分析处理任务。

Gawk

gawk(GNU awk)是UNIX awk的GNU版,为方便linux用户使用,通常将/bin/awk以符号链接方式链接到/bin/gawk,以迎合用户的使用习惯。(下文有提到gawk的地方均以awk代替)

awk的使用方式

1、命令行方式

awk [-F field-separator] ‘COMMAND’inputfiles

//其中COMMAND是awk的执行命令,用来处理数据,[-F field-separator]是可选选项,inputfiles是待处理文件。

//awk使用中,需要处理的文件,逐行使用分隔符分割成若干个字段,称之为域,分隔符默认是空格,可使用-F选项来指定分隔符

2、shell脚本模式

将所需执行的awk命令插入awk脚本文件,然后在首行设置命令解释器为#!/bin/awk,通过键入脚本名的方式调用。

3、所有awk命令写入到一个单独的文件,当处理同一类文件需求时,使用awk -f awk-script inputfiles调用之,其中awk-script指awk脚本。

awk的基本语法

awk [OPTION] 'program' FILE1 FILE2…

program:PATTERN{ACTION STATEMENT} //program由语句组成,各语句之间使用;隔开,整个program要用单引号引起来

OPTION:选项

-F:指定分割符

例,指定分隔符为“:”,打印出系统上各用户名和morenshell

# awk -F: '{print $1,$7}' /etc/passwd

-v:指定变量

例,通过-v选项指定变量a=hello awk 然后将其打印出来

# awk -v a="hello awk" '{print a}'

另外,也可以通过特殊模式BEGIN(模式下述)来指定变量,如上例,也可以这样写

# awk 'BEGIN{a="hello awk"}{print a}'

-f:指定脚本文件

awk变量

awk的变量,可分类为内置变量和自定义变量

1、内置变量

2、自定义变量

自定义变量有两种方式(上文基本语法中已有示例,此处不再赘述),但是,在脚本中仍然可以声明变量。

(1)、awk -v VARIABLE_NAME VARIABLE_VALUE 'program' inputfiles

(2)、awk 'BEGIN{VARIABLE_NAME VARIABLE_VALUE}ACTION STATEMENT}' inputfiles

3、变量使用示例

(1)、FS输入分隔符,默认为空格

例如,默认分隔符使用awk提取/etc/inittab中的“#”,如下图可以看到,如果以空格分割,第一个域即为#(忽略最后一行)

# awk '{print $1}' /etc/inittab //效果如下(最后一行请忽略)

以“:”为分隔符,提取系统中用户名以及用户默认

# awk -v FS=":" '{print $1,$7}' /etc/passwd

(2)、输出分隔符,默认为空格(如上图上例显示结果),接上例,以:为输出分隔符显示输出结果

# awk -v FS=":" -v OFS=":" '{print $1,$7}' /etc/passwd

(3)、NR和FNR

显示/etc/{inittab,passwd}所有内容以及行数

# awk '{print NR,$0}' /etc/{inittab,passwd}//看下图,行数不分开计数

# awk '{print FNR,$0}' /etc/{inittab,passwd}//看下图,使用FNR单独计数行数

# awk 'BEGIN{print "filename","alone_lines","unit_lines"}{print FILENAME,NR,FNR}' /etc/{passwd,inittab,group}//还可以这样写来分别显示总行号和单独行号,此处不再贴图

(4)、ARGC显示参数个数

# awk -F: '{print $1}END{print ARGC}' /etc/passwd //如下图,显示参数为二(经验证,貌似program也被识别成为一个参数,再加上后面的文件故为2个参数?)

awk的模式

1、Regular Expression 正则表达式

如其名,使用正则表达式匹配模式,在需要注意的是,在awk中使用正则表达式,匹配字符串要使用双斜线括起来,而后匹配到的行将被切片并分析处理,反之将略过。

取出/etc/passwd中包含root的行并打印出用户名和默认shell

# awk -F: ‘/root/ {print $1,$7}' /etc/passwd

2、Expression 表达式,当表达式的值为真(非零或非空)的行被匹配,仅处理匹配到的行

# awk -F: '$3>=500{print $1,$2,$3}' /etc/passwd

在此列出awk的常用操作符

如果模式自身是=,要写为/=/

条件表达式:

selector?if-true-express:if-false-express 只能是表达式不能使语句

条件表达式中,“:”两侧仅允许使用表达式而不能使用语句

# awk -F: '$3>=500?utype="common user":utype="admin or system user"{print $1 "is" utype} /etc/passwd

3、range行范围,有两种方式来定义此范围

(1)、pattern1,pattern2

从匹配到pattern1的行开始到匹配到pattern2的行为知,此范围的行被awk action处理

# awk 'NR==1,NR==10{print $1,$3,$7} /etc/passwd

4、特殊模式BEGIN和END

(1)、BEGIN在读取任何输入之前执行一次语句

# awk 'BEGIN{FS=":";OFS=":"}/root/{print $1,$3,$7} /etc/passwd

(2)、END在读取所有输入之后执行一次语句

# awk 'BEGIN{FS=":";OFS=":"}/root/{print $1,$3,$7}END{print "The end!"}' /etc/passwd

5、空模式

如果不指定模式则匹配文件中的所有行

awk重定向

1、输出重定向

awk可以使用shell的重定向符重定向输出,同样>代表覆盖式输出,>>代表追加。

覆盖式重定向

追加重定向效果

2、输入重定向

输入重定向需用到getline函数。getline从标准输入、管道或者当前正在处理的文件之外的其他输入文件获得输入。它负责从输入获得下一行的内 容,并给NF,NR和FNR等内建变量赋值。如果得到一条记录,getline函数返回1,如果到达文件的末尾就返回0,如果出现错误,例如打开文件失 败,就返回-1,可以结合到while等流控制语句使用。

通过例子说明输入重定向用法

(1)、awk 'BEGIN{"date" | getline d; print d}'

getling函数读取date命令的输出结果并将其赋值给自定义变量d,然后打印变量d

(2)、awk 'BEGIN{"date" | getline d; split(d,mon); print mon[3]}'

getine函数读取date命令输出的结果并赋值给自定义变量d,split函数将变量d转化为数组mon,然后打印数组mon的第三个元素。

(3)、awk 'BEGIN{while("ls" | getline) print}'

getline函数读取ls命令的输出结果而后打印显示

awk之print和printf

1、print

用法:print item1,item2….

要点:

(1)、各item之间使用,号隔开,输出时默认以空格分隔

(2)、输出的item可以是字符串或数值、当前分隔出来的域(字段,如$1)、变量或awk的表达式,数值会隐式转换为字符串输出。

(3)、print后面的item项可以省略,此时相当于打印$0即整行内容;print ""表示打印空白行。

例:

# awk 'BEGIN{print "line1","line2","line3"}'

# awk -F: '{print $1,$3,$7}' /etc/passwd

2、printf

用来格式话打印输出内容

(1)、格式:

printf format,item1,ietm2,…

(2)、要点

printf需要指定format;

format用于指定后面每个item的格式;

printf不能自行换行,如需换行需给定\n;

使用修饰符可以使输出格式更加美观。

(3)、format的格式指示符,以%开始,后跟一个字符

%c:显示字符的ASCII吗

%d,%i:十进制整数

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

%f:显示浮点数本身

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

%s:显示字符串

%u:显示无符号整数

%%:显示%自身

修饰符

#:字段的显示宽度

.#:取值精度

-:左对齐

=+:显示数值的符号

(4)、例:

取出系统用户的用户名和默认shell,要求用户名左对齐,占用15个字符,字符串显示;要求默认shell左对齐,占用20字符,字符串显示

awk -F: ‘{printf "%-15s %-20s\n",$1,$7}' /etcpasswd

使用显示浮点数自身(%f)的方式显示,会自动补全精度,长于精度部分将会执行四舍五入

# awk 'BEGIN{printf "%f\n",3.15}'

当使用数字来定义字段占用字符长度时,要放在其它修饰符前面;小数点后面的数字代表精度

# awk 'BEGIN{printf "%-15.2\n",3.15}'

awk之action

1、常见action

(1)、表达式 Expression

(2)、控制语句 Control statements

(3)、组合语句 Commpound statments

(4)、输入语句 Input statments

(5)、输出语句 Output statements

2、awk常见控制语句以及使用示例

(1)、if-else语句 格式:if (condition) {then body} else {else body}

# awk -F: '{if($3>=500{print $1 "is a common user"} else {print $1 "is admin or systemuser"}' /etc/passwd

uid号大于等于500的显示为普通用户,小于500的显示为管理员或系统用户。

# awk -F: '{if(NF>=8){print}}' /etc/inittab

打印显示以冒号切割形成字段大于等于8的行

(2)、while语句 格式: 格式:while (condition) {while body}

awk '{i=1;while(i<=NF){printf "%s ",$i;i+=2}; print ""}' /etc/inittab

打印输出/etc/inittab中的奇数字段

打印出字符大于等于6的字段

# awk '{i=1;while(i<=NF{if(length($i<=6){print $i};i++}}' /etc/inittab

(3)、do-while循环 格式:格式:do {do-while body} while (condition)

# awk 'BEGIN{sum=0;i=0;do{sum+=i;i+=}while{i<=100};print sum;}'

求和1-100

(4)、for循环 格式:for (variable assignment; condition; iteration process) {for body}

# awk '{for(i=1,i<=NF,i+=2){printf "%s ",$1};print ""}' /etc/inittab

打印出/etc/inittab中的每行的奇数字段

for循环还可以用来遍历数组 格式:for (i in array) {for body}

# awk 'BEGIN{"date" | getline d; split(d,test);for (i in test) print test[i]}'

break 用于在满足条件的情况下跳出循环;continue用于在满足条件时忽略后面的语句,直接返回循环的顶端

(5)、next提前结束本行处理,进入下一行处理

取uid为奇数的用户和uid

# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd

(6)、数组

关联数组

array[index-expression]index-expression:可以使用任意字符串;如果某数组元素事先不存在,那么在引用时,awk会自动创建次元素并将其初始化为空串;因此,要判断某数组是否存在某元素,必须使用“index in array”这种格式A[first]="hello awk"print A[second]要遍历数组中的每一个元素,需要使用如下特殊结构:for (var in array) {for body}期中var会遍历array的索引,而非元素的值

(7)、awk的内置函数 split(string,array[,fieldsep[,seps]])能够将string标示的字符串以fieldsep为分隔符进行切片,并切片后的结果保存至array为名的数组中;数组下表从1开始

# awk 'BEGIN{split("root:x:0:0",user,":");for (i in user) print user[i]}'

由于本人水平有限,awk的使用先总结到这里吧,在以后的使用中再深入研究。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2015-10-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 马哥Linux运维 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云 BI
腾讯云 BI(Business Intelligence,BI)提供从数据源接入、数据建模到数据可视化分析全流程的BI能力,帮助经营者快速获取决策数据依据。系统采用敏捷自助式设计,使用者仅需通过简单拖拽即可完成原本复杂的报表开发过程,并支持报表的分享、推送等企业协作场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档