Linux集群和自动化维2.5 awk的基础用法及实用示例-阿里云开发者社区

开发者社区> 华章出版社> 正文

Linux集群和自动化维2.5 awk的基础用法及实用示例

简介:

2.5 awk的基础用法及实用示例


1. awk工具简介

awk是一个强大的文本分析工具,相对于grep的查找、sed的编辑,awk在对数据进行分析并生成报告时,显得尤为强大。简单来说,awk就是把文件逐行地读入,然后以空格为默认分隔符将每行进行切片,切开的部分再进行各种分析处理。awk的名称得自于它的创始人Alfred Aho、Peter Weinberger 和Brian Kernighan 姓氏的首个字母。实际上awk的确拥有自己的语言:awk程序设计语言,三位创建者已将它正式定义为“样式扫描和处理语言”。

awk允许我们创建简短的程序,这些程序可读取输入文件、为数据排序、处理数据、对输入执行计算及生成报表,还有无数其他的功能。

2.使用方法

awk的命令格式如下:

awk 'pattern {action}' filename

其中,pattern就是要表示的正则表达式,它表示awk在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。

awk语言的最基本功能是在文件或字符串中基于指定的规则浏览和抽取信息,在抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。

通常,awk是以文件的一行为处理单位的。awk每接收文件的一行后,就会执行相应的命令来处理文本。

下面介绍一下awk程序设计模型。

awk程序由3部分组成,分别为:

初始化(处理输入前做的准备,放在BEGIN块中)

数据处理(处理输入数据)

收尾处理(处理输入完成后要进行的处理,放到END块中)

其中,在“数据处理”过程中,指令被写成一系列模式/动作过程,模式用于测试输入行的规则,以确定是否将规则应用于这些输入行。

3. awk调用方式

awk主要有三种调用方式,下面分别来看看。

(1)命令行方式

awk [-F  field-separator] 'commands' filename

其中,commands是真正的awk命令,[-F域分隔符]是可选的,filename是待处理的文件。

在awk文件的各行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。

(2)使用-f选项调用awk 程序

awk允许将一段awk 程序写入一个文本文件中,然后在awk 命令行中用-f 选项调用并执行这段程序,命令如下:

awk -f awk-script-file filename

其中,-f选项加载awk-script-file中的awk脚本,filename表示文件名。

(3)利用命令解释器调用awk 程序

利用Linux系统支持的命令解释器功能可以将一段awk 程序写入文本文件中,然后在它的第一行加上#!/bin/awk –f。

4. awk详细语法

与其他Linux命令一样,awk 拥有自己的语法:

awk [ -F re] [parameter...] ['prog'] [-f progfile][in_file...]

其中,

-F re:允许awk更改其字段分隔符。

parameter:该参数帮助为不同的变量赋值。

prog:awk的程序语句段。这个语句段必须用单引号'和'括起,以防被Shell解释。

前面已经提到过这个程序语句段的标准形式,如下所示:

awk 'pattern {action}' filename

其中pattern 参数可以是egrep 正则表达式中的任何一个,它可以使用语法/re/再加上一些样式匹配技巧构成。与sed 类似,也可以使用“,”分开两种样式以选择某个范围。

action参数总是被大括号包围,它由一系列awk语句组成,各语句之间用“;”分隔。awk会解释它们,并在pattern给定的样式匹配记录上执行相关操作。

事实上,在使用该命令时可以省略pattern和action两者中的某一个,但不能两者同时省略。省略pattern表示没有样式匹配,对所有行(记录)均执行操作;省略action表示执行默认的操作—在标准输出上显示。

-f progfile:允许awk 调用并执行progfile指定的程序文件。progfile是一个文本文件,它必须符合awk 的语法。

in_file:awk的输入文件,awk 允许对多个输入文件进行处理。值得注意的是awk 不修改输入文件。

如果未指定输入文件,awk 将接受标准输入,并将结果显示在标准输出上。

5. awk脚本编写

(1)awk的内置变量

awk的内置变量主要有如下几种。

FS:输入数据的字段分隔符。

RS:输入数据的记录分隔符。

OFS:输出数据的字段分隔符。

ORS:输出数据的记录分隔符。另一类是系统自动改变的,比如:NF表示当前记录的字段个数,NR表示当前记录的编号等。

举个例子,可用如下命令打印passwd中的第1个和第3个字段:

awk -F ":" '{ print $1 "" $3 }'  /tmp/passwd

(2)pattern/action模式

awk程序部分采用了pattern/action模式,即针对匹配pattern的数据,使用action逻辑进行处理。来看下面这两个例子。

判断当前是不是空格,命令如下:

/^$/ {print "This is a blank line!"}

判断第5个字段是否含有“MA”,命令如下:

$5 ~ /MA/ {print $1 "," $3}

(3)awk与Shell混用

因为awk可以作为一个Shell命令使用,因此awk能与Shell脚本程序很好地融合在一起,这点为实现awk与Shell程序的混合编程提供了可能。实现混合编程的关键是awk与Shell脚本之间的对话,换言之,就是awk与Shell 脚本之间的信息交流:awk从Shell脚本中获取所需的信息(通常是变量的值)、在awk 中执行Shell命令行、Shell脚本将命令执行的结果送给awk处理,以及Shell脚本读取awk的执行结果等,另外需要注意的是在Shell脚本中读取awk变量的方式,一般是通过" '$变量名' "的方式来读取Shell程序中的变量。

6. awk内置变量

awk有许多内置变量用于设置环境信息,这些变量可以被改变,下面列举了工作中最常用的一些awk变量,变量及其意义如下所示:

ARGC               命令行参数个数

ARGV               命令行参数排列

ENVIRON            支持队列中系统环境变量的使用

FILENAME           awk浏览的文件名

FNR                浏览文件的记录数

FS                 设置输入域分隔符,等价于命令行 -F选项

NF                 浏览记录的域的个数

NR                 已读的记录数

OFS                输出域分隔符

ORS                输出记录分隔符

RS                 控制记录分隔符

此外,$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域……依次类推。

7. awk中的print和printf

awk中同时提供了print和printf两种用于打印输出的函数。

其中print函数的参数可以是变量、数值或字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就会串联在一起而无法区分。这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。

printf函数,其用法和C语言中printf函数基本相似,可以格式化字符串,输出复杂结果时,printf的显示结果更加人性化。

使用示例如下所示:

awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\       n",FILENAME,NR,NF,$0)}' /tpm/passwd 

命令显示结果如下所示:

filename:/tmp/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash

filename:/tmp/passwd,linenumber:2,columns:7,linecontent:bin:x:1:1:bin:/bin:/sbin/nologin

filename:/tmp/passwd,linenumber:3,columns:7,linecontent:daemon:x:2:2:daemon:/sbin:/sbin/nologin

filename:/tmp/passwd,linenumber:4,columns:7,linecontent:adm:x:3:4:adm:/var/adm:/sbin/nologin

filename:/tmp/passwd,linenumber:5,columns:7,linecontent:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

filename:/tmp/passwd,linenumber:6,columns:7,linecontent:sync:x:5:0:sync:/sbin:/bin/sync

filename:/tmp/passwd,linenumber:7,columns:7,linecontent:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

filename:/tmp/passwd,linenumber:8,columns:7,linecontent:halt:x:7:0:halt:/sbin:/sbin/halt

filename:/tmp/passwd,linenumber:9,columns:7,linecontent:mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

filename:/tmp/passwd,linenumber:10,columns:7,linecontent:uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

filename:/tmp/passwd,linenumber:11,columns:7,linecontent:operator:x:11:0:operator:/root:/sbin/nologin

filename:/tmp/passwd,linenumber:12,columns:7,linecontent:games:x:12:100:games:/usr/games:/sbin/nologin

filename:/tmp/passwd,linenumber:13,columns:7,linecontent:gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

filename:/tmp/passwd,linenumber:14,columns:7,linecontent:ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

filename:/tmp/passwd,linenumber:15,columns:7,linecontent:nobody:x:99:99:Nobody:/:/sbin/nologin

filename:/tmp/passwd,linenumber:16,columns:7,linecontent:vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin

filename:/tmp/passwd,linenumber:17,columns:7,linecontent:saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin

filename:/tmp/passwd,linenumber:18,columns:7,linecontent:postfix:x:89:89::/var/spool/postfix:/sbin/nologin

filename:/tmp/passwd,linenumber:19,columns:7,linecontent:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

filename:/tmp/passwd,linenumber:20,columns:7,linecontent:puppet:x:52:52:Puppet:/var/lib/puppet:/sbin/nologin

filename:/tmp/passwd,linenumber:21,columns:7,linecontent:ntp:x:38:38::/etc/ntp:/sbin/nologin

filename:/tmp/passwd,linenumber:22,columns:7,linecontent:nagios:x:500:500::/home/nagios:/bin/bash

filename:/tmp/passwd,linenumber:23,columns:7,linecontent:apache:x:48:48:Apache:/var/www:/sbin/nologin

filename:/tmp/passwd,linenumber:24,columns:7,linecontent:nginx:x:498:499:nginx user:/var/cache/nginx:/sbin/nologin

参考文档http://blog.pengduncun.com/?p=876。

8.工作示例

截取出init 中PID的示例命令如下:

ps -aux | grep init | grep -v grep | awk '{print $2}'

截取网卡eth0的IPv4地址,示例命令如下:

ifconfig eth0 |grep "inet addr:" | awk -F: '{print $2}' |awk '{print $1}'

找出当前系统的自启动服务,示例命令如下:

chkconfig --list |grep 3:on | awk '{print $1}'

取出vmstat第4项的平均值,示例命令如下:

vmstat 1 4 | egrep -v "io|free" | awk '{sum+=$4} END{print sum/4}'

以|为分隔符,汇总/yundisk/log/hadoop/下的hadoop第9项日志并打印,示例命令如下:

cat /yundisk/log/hadoop/hadoop_clk_*.log | awk -F '|' 'BEGIN{count=0} $2>0             {count=count+$9} END {print count}'

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

华章出版社

官方博客
官网链接