awk是Linux下优良的文本处理工具,有自成一体的编程语法规则,在循环和条件判断语句等方面和C语言很像。

其一般形式是:Pattern1 {ACTIONS; } Pattern2 { ACTIONS; },其中Pattern可以理解为条件(类似if语句),当满足相应条件时,执行相应的ACTIONS。

awk的功能十分强大,涉及的内容也非常广泛,以下仅记述笔者认为最为重要和常用的内容。

1、关键内置参数和指令块

内置参数:

FS:输入字段分隔符,默认是空格

OFS:输出字段分隔符,默认也是空格

NF:每一行 ($0) 拥有的栏位总数

NR:所处理的是总共『第几行』

FNR:所处理的是当前文件『第几行』

注意:只有一个文件时,FNR与NR相等。

指令块:

BEGIN{}:在按行处理文件之前执行BEGIN块内指令,一般用来初始化相关参数。

END{}:在按行处理文件之后执行END块内指令,一般用来输出最终结果。

2、理解按行处理

使用awk时,要明确{ACTIONS}对应的是每一行的处理动作;而且更加强大的是,各行的信息可以保留在变量里,供后续使用。

示例(a):将passwd文件内容作为输入,FS=":"指定分隔符为冒号;当第三个字段$3<10时,执行打印$1和$3的任务。

cat /etc/passwd | \
awk 'BEGIN {
FS=":"
}
$3 < 10 {
print $1"\t " $3
}'

示例(b):计算销售文件xs中的销售总金额:假设销售金额在记录的第三个字段,总金额保存在变量total中,最后打印出销售金额总计。

$awk -F ":" '{
print $3; #打印每一行的销售金额
total=total+$3;
}
END {
printf "销售金额总计:%.2f",total #打印总销售金额
}' xs

3、数组的使用

个人觉得数组是awk中最有用处的数据结构,大大提升了awk的效能。awk中的数组的下标可以是数字或字母,称为关联数组,能够辅助计数、存储,类似于python中的字典类型。

ü  用变量作为数组下标。如:$ awk{name[x++]=$2};END{for(i=0;i<NR;i++) print i,name[i]}' test。数组name中的下标是一个自定义变量x,awk初始化x的值为0,在每次使用后增加1。第二个域的值被赋给name数组的各个元素。在END模块中,for循环被用于循环整个数组,从下标为0的元素开始,打印那些存储在数组中的值。下标是关健字,它不一定从0开始,可以从任何值开始。

ü  for 循环用于读取关联数组中的元素。格式如下:

{
for (item in arrayname){
print arrayname[item]
}
}
#使用数组遍历输出所有以tom开头的行。
$ awk'/^tom/{
name[NR]=$1
};
END{
for(i in name){
printname[i]
}
}' test

ü  用字符串作为下标。如:count["test"]

ü  用域值作为数组的下标。一种新的for循环方式,for(index_value in array) statement。如:awk '{count[$1]++}END{for(name in count) print name,count[name]}' test。该语句将打印$1中不同字符串出现的次数。它首先以第一个域作数组count的下标,第一个域内容变化,索引就变化。

ü  delete 函数用于删除数组元素。如:$ awk '{line[x++]=$1} END{for(x in line)delete(line[x])}' test。分配给数组line的是第一个域的值,所有记录处理完成后,for循环将删除每一个元素。

应用举例:

使用数组合并两个文件,其中NR==FNR时处理前一个文件,NR>FNR时处理后一个文件。

awk -F ","  'BEGIN{
OFS=","
}
NR==FNR{
a[$1]=$0 # $1为第一个文件中的userid字段
}
NR>FNR && NF>3{ #行字段大于3个的行
gsub("","",$3);
if(a[$3]!="")print $0,a[$3] #$3为第二个文件的userid字段
}' file1 file2

4、应用正则匹配

使用awk处理文件时,常常有这样的需求:当行中包含某一字符串时,就进行相应的操作。正则匹配的原理简单,但功能相当强大,以下直接使用范例来说明。

范例参考:http://www.cnblogs.com/zhuyp1015/archive/2012/07/14/2591822.html

假设有这样一个待处理的文件"grade.txt":

M.Tansley         05/99        48311       Green       8       40     44

J.Lulu        06/99        48317       green        9       24     26

P.Bunny    02/99        48     Yellow       12     35     28

J.Troll        07/99        4842         Brown-3   12     26     26

L.Tansley  05/99        4712         Brown-2   12     30     28

#非精确匹配,第3个字段包含“48”时则打印
$ awk '$3 ~/48/ {print $0}' grade.txt
#精确匹配,第3个字段等于48时则打印
$ awk '$3=="48" {print $0}'grade.txt
#不区分首字母的大小写,匹配含Green或者green的行
$ awk '/[Gg]reen/' grade.txt
#匹配第一个域的第四个字符是‘a’的行
$ awk '$1 ~/^...a/' grade.txt
# “或”匹配,使用‘|’
$ awk '$0 ~/(Yellow|Brown)/' grade.txt
#也可以这样,不加括号
$ awk '$0 ~/Yellow|Brown/' grade.txt

5、格式化输出

大多数情况下使用print就能解决问题,但有时候我们需要使用格式化输出,awk中的printf()和sprintf()都可以进行格式化输出,语法规则几乎与C语言完全相同。

printf()将字符串打印到stdout。在使用printf()时,不会像print()一样自动打印换行符,需要自己在字符串末尾添加"\n"符号。

# cat grade.txt | \
awk 'NR==1{printf "%10s %10s %10s %10s%10s\n",$1,$2,$3,$4,"Total" }

sprintf()返回可赋值给变量的格式化字符串。

根据 Format 参数指定的sprintf 子例程格式字符串来格式化Expr 参数指定的表达式并返回最后生成的字符串。

sprintf(Format, Expr, Expr, . . . )
cat grade.txt |awk'NR==1{a=sprintf("%10s\n",$3); print a}'

6、shell变量的引用

awk中不能像引用自身变量一样引用shell变量,可用的引用方式如下:

(1)使用引号"'$var'"

这种写法大家无需改变用'括起awk程序的习惯,是老外常用的写法.如:

var="test"
awk 'BEGIN{print "'$var'"}'

(2)使用-v选项

假设shell中有:var="this is a test",则在awk中可以这样引用:

awk –v nvar="$var" 'BEGIN{print nvar}'

7、增加代码可读性

有些人习惯将所有的awk语句写到一行,而且没有注释;如果只是要实现简单的功能,这样没什么问题,但是当需要实现的功能比较复杂时,则这样操作不利于代码的阅读、维护和重用。

关于增加代码的可读性,有以下几个方面值得注意:

1)使用注释:与bash一样,awk的注释符号也是“#”。

2)使用缩进和换行:在awk中换行和缩进都不会影响代码的执行,而且好的排版可以大大增强可读性。

awk入门及进阶的更多相关文章

  1. SQL Server 扩展事件(Extented Events)从入门到进阶(1)——从SQL Trace到Extented Events

    由于工作需要,决定深入研究SQL Server的扩展事件(Extended Events/xEvents),经过资料搜索,发现国外大牛的系列文章,作为“学习”阶段,我先翻译这系列文章,后续在工作中的心 ...

  2. Wireshark入门与进阶系列(一)

    摘自http://blog.csdn.net/howeverpf/article/details/40687049 Wireshark入门与进阶系列(一) “君子生非异也,善假于物也”---荀子 本文 ...

  3. Wireshark入门与进阶系列(二)

    摘自http://blog.csdn.net/howeverpf/article/details/40743705 Wireshark入门与进阶系列(二) “君子生非异也,善假于物也”---荀子 本文 ...

  4. Wireshark入门与进阶---数据包捕获与保存的最基本流程

    Wireshark入门与进阶系列(一) "君子生非异也.善假于物也"---荀子 本文由CSDN-蚍蜉撼青松 [主页:http://blog.csdn.net/howeverpf]原 ...

  5. [转]shell awk 入门,中级,高级使用

    awk很常用,对于我们在shell中分析log和file很有好处,很实用的东西,大家一起分享学习- 作为技术支持工程师,我们最最经常的工作就是要处理文本文件,不管是什么数据库最后都可以导成文本,我们就 ...

  6. SQL Server AlwaysON从入门到进阶(3)——基础架构

    本文属于SQL Server AlwaysON从入门到进阶系列文章 前言: 本文将更加深入地讲解WSFC所需的核心组件.由于AlwaysOn和FCI都需要基于WSFC之上,因此我们首先要了解在Wind ...

  7. SQL Server AlwaysON从入门到进阶(2)——存储

    本文属于SQL Server AlwaysON从入门到进阶系列文章 前言: 本节讲解关于SQL Server 存储方面的内容,相对于其他小节而言这节比较短.本节会提供一些关于使用群集或者非群集系统过程 ...

  8. SQL Server AlwaysON从入门到进阶(1)——何为AlwaysON?

    本文属于SQL Server AlwaysON从入门到进阶系列文章 本文原文出自Stairway to AlwaysOn系列文章.根据工作需要在学习过程中顺带翻译以供参考.系列文章包含: SQL Se ...

  9. SQL Server 扩展事件(Extented Events)从入门到进阶(4)——扩展事件引擎——基本概念

    本文属于 SQL Server 扩展事件(Extented Events)从入门到进阶 系列 在第一二节中,我们创建了一些简单的.类似典型SQL Trace的扩展事件会话.在此过程中,介绍了很多扩展事 ...

随机推荐

  1. Linux下查看相应端口的进程

    1)查找被占用的端口:netstat -tln | grep 7777 2)查看被占用端口的PID:lsof -i:7777 3)禁用使用kill -9 PID来禁用端口进程

  2. 媒体查询漫谈——@media Queries

    通过不同的媒体类型和条件定义样式表规则.媒体查询让CSS可以更精确作用于不同的媒体类型和同一媒体的不同条件.媒体查询的大部分媒体特性都接受min和max用于表达”大于或等于”和”小与或等于”.如:wi ...

  3. WDA基础三:简单的INPUT选择,简单的TABLE显示

    先从基本的开始,简单的单选和TABLE显示 1.创建选择条件节点,CONTEXT页签,右键CONTEXT创建NODE,对应1:1  1:1  lead selection 2.创建结果节点,对应0:n ...

  4. 时间序列 ARIMA 模型 (三)

    先看下图: 这是1986年到2006年的原油月度价格.可见在2001年之后,原油价格有一个显著的攀爬,这时再去假定均值是一个定值(常数)就不太合理了,也就是说,第二讲的平稳模型在这种情况下就太适用了. ...

  5. 字符序列(characts)

    字符序列(characts) 问题描述: 从三个元素的集合[A,B,C]中选取元素生成一个N 个字符组成的序列,使得没有两个相邻的 子序列(子序列长度=2)相同,例:N=5 时ABCBA 是合格的,而 ...

  6. Xcode下的中文乱码问题

    Xcode下的中文乱码问题 转载自:http://linyehui.me/2014/07/09/convert-gbk-to-utf8-on-mac.html =========== 问题原因 绝大部 ...

  7. 简述Spring容器与SpringMVC的容器的联系与区别

    简述Spring容器与SpringMVC的容器的联系与区别 2017年07月04日 10:55:07 阅读数:6260 摘要: 在Spring整体框架的核心概念中,容器的核心思想是管理Bean的整个生 ...

  8. jquery自定义类的封装

    如何用jquery自定义一个类?(demo参考) /*简单使用*/ (function($){ //el操纵对象,option属性值 $.love = function(el,option){ var ...

  9. 1-1Controller之Request

    laravel5.5版本 //路由: Route::any('request1',['uses'=>'StudentController@request1']); //控制器中的方法: publ ...

  10. Win10系列:JavaScript 项目模板和项模板

    使用Visual Studio 开发Windows应用商店应用时,通过其提供的模板可以帮助我们快速地创建一个应用.其中,在新建一个Windows应用商店应用程序项目时可以在项目模板中选择所需要的模板类 ...