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. Leetcode 1008. 先序遍历构造二叉树

    1008. 先序遍历构造二叉树  显示英文描述 我的提交返回竞赛   用户通过次数169 用户尝试次数183 通过次数171 提交次数247 题目难度Medium 返回与给定先序遍历 preorder ...

  2. MIR7预制发票扣除已经预制的数量(每月多次预制,未即时过账)

    业务场景见抬头,有没有标准的解决方案就不说了,也没去考虑... 这个增强还是SAP老表提供的,感谢,省了不少时间. INCLUDE:LMR1MF6S 最后的位置 ENHANCEMENT ZMIR7_0 ...

  3. 数据结构与算法之PHP查找算法(顺序查找)

    对于查找数据来说,最简单的方法就是从列表的第一个元素开始对列表元素逐个进行判断,直到找到了想要的结果,或者直到列表结尾也没有找到,这种方法称为顺序查找. 一.基本写法 顺序查找的实现很简单.只要从列表 ...

  4. 将本地项目推送至gitee或者github

    将本地项目推送到Git github上的版本和本地版本冲突的解决方法 初始化项目时,在git中新建项目. 在Github中创建了一个Repository之后,会给你列出如何将自己本地项目Push到Gi ...

  5. Java线程池理解及用法

    前言 多线程的异步执行方式,虽然能够最大限度发挥多核计算机的计算能力,但是如果不加控制,反而会对系统造成负担.线程本身也要占用内存空间,大量的线程会占用内存资源并且可能会导致Out of Memory ...

  6. input实时监听

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  7. python javar send

    # -*- coding: utf-8 -*-import jpypeimport os.pathjarpath = os.path.join(os.path.abspath('.'), 'axja' ...

  8. Linux 硬件信息命令

    # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理CPU个数cat /proc/cpuinfo| g ...

  9. ubuntu ssh前后台切换命令相关

    后台运行:命令+& 例如 sleep 60 & jobs -l 显示job的pid和状态 ps 显示用户进程 将第一个job切换回前台:fg 1 放到后台:bg 1 cltr + z ...

  10. linux操作系统及命令Part 2

    cat 命令 cat .txt .txt .txt > Ta.txt 将左边三个文件纵向合并为Ta文件 cat .txt>> Ta.txt 将左边文件的内容添加到Ta文件中 tar ...