Linux awk命令-强大的文本分析工具

作者: 云中布衣   分类:  学习笔记    热度: (550℃)   时间: 2017-7-27 15:37   标签: #Linux命令    

awk是Unix/Linux下的一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单的来说awk就是把文件逐行读入,以空格为默认分隔符将其切片,再对切开的部分进行各种分析处理。

awk有3个不同的版本:awk、nawk和gawk。现在默认Linux系统下日常使用的是gawk。awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。AWK提供了及其强大的功能:可以进行样式表的装入、流控制、数学运算符、进程控制语句甚至于内置变量和函数。实际上 AWK 的确拥有自己的语言:AWK 程序设计语言,三位创建者已将它正式定义为“样式扫描和处理语言”。它允许你创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他功能。

下面先举一个例子:查找/etc/passwd文件中所有用户名以s开头的账号并累计产生相应的序列号,一起输出出来。

cat /etc/passwd | awk -F ':' 'BEGIN{count=0;}/^s/{name[count]=$1;count++;}END{for(i=0;i<NR;i++){print i,name[i];}}'
输出结果如下:

选区_116.png

我们来分析以下上面命令执行的过程:首先通过cat命令读取/etc/passwd文件中的内容,然后利用管道技术将内容重定向给awk处理。-F ":"表示采用":"分隔符用来切割行内容,然后/^s/模式匹配所有以s开头的用户名,count是定义的变量初始化为0,$1表示切割行内容中第一个元素内容,将其存储到数组name中,下标为count,后面在通过一个for循环将i和name[i]输出出来,循环上限NR为awk的内置变量表示已读出的记录数。BEGIN{...}表示读取前的初始化操作,中间{...}表示action部分,读取时的操作,最后的END{...}表示读取完成后的结束操作。通过这个命令我们对于awk命令大致有了一个了解。

这个命令在输出的时候会有一个问题,就是9序号往后数组里面没有东西了,但是i还是在运行,这是因为NR表示的是已读出的记录数,比符合/^s/模式的记录要多,因此我们可以在END模块的for循环中加一个if条件语句来判断name[i]中是否有值,再决定是否输出。

使用方法

awk 'pattern + action'  filename

尽管操作可能会很复杂,但语法总是这样,其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。pattern就是要表示的正则表达式,用斜杠括起来。awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。

调用awk命令

1.命令行方式

awk [-F  field-separator]  'commands'  input-file(s)

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

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

当然我们也可以利用管道技术,对其他的Linux命令输出的信息进行awk文本分析,就像上面的例子一样

2.shell脚本方式

将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。

相当于shell脚本首行的:#!/bin/sh

可以换成:#!/bin/awk

3.将所有的awk命令插入一个单独文件,然后调用

awk -f awk-script-file input-file(s)

其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。

awk内置变量

awk有许多内置变量用来设置环境信息,这些变量可以被改变,前面的例子中的NR就是一个内置变量

\$n 当前记录的第n个字段,字段间由FS分隔

\$0 完整的输入记录

ARGC 命令行参数的数目

ARGIND 命令行中当前文件的位置(从0开始算)

ARGV 包含命令行参数的数组

CONVFMT 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组

ERRNO 最后一个系统错误的描述

FIELDWIDTHS 字段宽度列表(用空格键分隔)

FILENAME 当前文件名

FNR 各文件分别计数的行号

FS 字段分隔符(默认是任何空格)

IGNORECASE 如果为真,则进行忽略大小写的匹配

NF 输入字段分割符

NR 已经读出的记录数,就是行号,从1开始

OFMT 数字的输出格式(默认值是%.6g)

OFS 输出记录分隔符(输出换行符),输出时用指定的符号代替换行符

ORS 输出记录分隔符(默认值是一个换行符)

RLENGTH 由match函数所匹配的字符串的长度

RS 记录分隔符(默认是一个换行符)

RSTART 由match函数所匹配的字符串的第一个位置

SUBSEP 数组下标分隔符(默认值是/034)

借助printf的格式化输出字符串来替代print可以使得代码更加的简洁

此外我们可以使用变量、条件语句、循环语句、数组来进行awk编程

比如,我们可以统计某个文件夹下的文件占用的字节数,过滤掉4096大小的文件(一般是指文件夹)

$ ls -l | awk 'BEGIN{size=0;}{if($5 != 4096){size = $5+size;}}END{print "[end]size:",size;}'
[end]size: 2016824237

内置函数

awk之所以成为一种优秀的程序设计语言的原因之一是它吸收了某些优秀的程序设计语言(例如C)的许多优点。除了前面的变量,条件语句,循环语句以及数组,内置函数也是其中之一。例如awk使用了一系列的字符串处理内置函数,它们与C语言的字符串处理函数相似,使用方式也相差无几。

gsub(r,s):在整个$0中用s代替r

gsub(r,s,t):在整个t中用s替代r

index(s,t):返回s中字符串t的第一位置

length(s):返回s长度

match(s,r):测试s是否包含匹配r的字符串

split(s,a,fs):在fs上将s分成序列a

sprint(fmt,exp):返回经fmt格式化后的exp

sub(r,s):用$0中最左边最长的子串代替s

substr(s,p):返回字符串s中从p开始的后缀部分

substr(s,p,n):返回字符串s中从p开始长度为n的后缀部分

比如,我们找出当前文件夹下文件名长度大于10的所有文件,并将它们输出出来

$ ls -l | awk '{if(length($9) > 10){print $9;}}'
awk的内容非一篇文章能够详尽的,更多的内容可以访问:http://www.runoob.com/linux/linux-comm-awk.html

或者GNU的官网中介绍信息https://www.gnu.org/software/gawk/manual/gawk.html

再或者直接在终端中man awk就能获得更为详细的信息,祝你好运!

(完)


56.8K

发表评论:

© 云中布衣 2015 | Driven by EMLOG  | SiteMap | RunTime: 7.96ms RSS  | MORE  |   | TOP

文章数量【258】 评论数量【238】 稳定运行【1210天】

Visitor IP Address【54.82.73.21】

Email:ieeflsyu#outlook.com