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. Jupyter notebook 转 pdf [完整转换]

  2. Java对MongoDB中的数据查询处理

    Java语言标准的数据库时MySQL,但是有些时候也会用到MongoDB,这次Boss交代处理MongoDB,所以讲代码以及思路记录下了 摸索的过程,才发现软件的适用还是很重要的啊!!! 我连接的Mo ...

  3. k8s相关端口表-以及周边工具

    k8s端口 kube-api 6443 kube-controller-manager 10252 kube-scheduler 10251 kubelet 10250 kube-proxy 1025 ...

  4. hdu-6341-搜索

    Problem J. Let Sudoku Rotate Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K ...

  5. Oracle11g温习-第十四章:约束( constraint )

    2013年4月27日 星期六 10:48 1.约束的功能 通过一些强制性商业规则,保证数据的完整性.一致性 2.约束的类别 1 )  not null    不允许为空     2 )  check  ...

  6. 函数使用一:采购订单BAPI_PO_CREATE1

    REPORT YTEST01. DATA:GS_POHEADER TYPE BAPIMEPOHEADER, GS_POHEADERX TYPE BAPIMEPOHEADERX, GT_RETURN T ...

  7. C# 3.0 / C# 3.5 扩展方法

    概述 扩展方法是一种特殊的静态方法,可以像扩展类型上的实例方法一样进行调用,能向现有类型“添加”方法,而无须创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法的定义实现: public s ...

  8. 使用CSDN-markdown编辑器

    欢迎使用Markdown编辑器写博客 本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接 ...

  9. PHPCMS V9完全开发介绍

    PHPCMS V9 文件目录结构: 根目录 | – api 接口文件目录 | – caches 缓存文件目录 | – configs 系统配置文件目录 | – caches_* 系统缓存目录 | – ...

  10. 【转】EF 获取类的属性并排除特定属性(getType().GetProperties())

    当获取一个类型(class)的所有属性时,想排除指定属性,该如何操作? 比如:EF中一个实体类型UserEntity,通过反射获取这个类的属性时,想排除这个为映射的字段ID 使用以下方法即可! Pro ...