自己慢慢积累。
分类: LINUX
2015-10-29 17:14:39
摘抄了 http://blog.csdn.net/sosodream/article/details/6276758 的部分章节。
实例:正则效率。
需求:某文本以空格和/进行分隔,获取第五列的内容.
方法1:采用正则[ /]分别匹配二种分隔符,取得第五列
# time awk -F'[ /]' '{print $5}' a.txt >/dev/null
real 0m17.717s
user 0m14.749s
sys 0m2.844s
方法2:实际数据分析中发现,可以采用单字符解析的方式,首先根据“空格”分隔符取得第4列,再利用“/”分隔符取得第二列。
# time awk '{print $4}' a.txt |awk -F/ '{print $2}' >/dev/null
real 0m0.565s
user 0m0.224s
sys 0m0.688s
实例结果分析:awk采用-F指定分隔符,在多分隔符情况下,会启用正则去解析记录,增加了函数调用,和字符串匹配的消耗,效率上理所当然的比不上默认的空格或单字符分隔符采用的简单的字符比较方式,尽管如此,方法2依赖于对需求的进一步分析,适用的需求范围没有使用正则那么简便灵活。
执行模式涉及工具内部的程序流程和处理逻辑,不同的程序一般具有自身的执行模式,但同时也遵守着一些通用的标准。比如《GNU Coding Standards》(Richard Stallman,1993)一文中关于GNU兼容接口提到一点:如果程序按行读取输入则应该每次只在内存中保留一行,以便于支持大文件操作。实际上,很多工具软件正是采用这种方式进行处理的。比如grep、awk、sed等命令的一般执行模式便是每次读取一行输入,再执行指定的操作,保证了程序执行时的低内存消耗。
在shell编程的各种应用工具,用以文本处理的较为常用的命令以sed和awk为典型代表,其执行模式也颇具特色。
sed是一个POSIX.2标准支持的流编辑程序。sed在执行过程中利用了二个可以操作的空间:模式空间和缓冲空间,和一个可控制的操作循环(cycle)。 sed的执行模式的便是基于这样一个循环操作:读入一行文本进入模式空间并执行操作,直到输入结束或主动退出。
sed的魅力便在于利用这二个空间和操作循环所进行的运算及由此产生的强大功能,这种强大充分体现在sed运算的图灵完备性:单个sed命令可以模拟所有图灵运算。简单的说,单个sed命令可以实现任何的运算任务。尽管如此,限于sed的执行模式和效率考虑,一般情况下却不将sed 用于文本操作外的计算比如数学运算等,sed通常应用于文本的查询,替换,过滤等操作。
了解了sed的执行模式,我们就可以通过控制sed的循环,采用合理的程序逻辑以提高命令执行效率。
实例:sed应用,读取指定行
方法1:sed -n '45,50p' filename
方法2:sed -n '51q;45,50p' filename
实例结果分析:方法2在方法1基础上增加了一个判断,当文件读取到第51行时即时退出。避免文件后续部分的遍历,在大数据量处理上能够很大的提高执行效率。
实例:sed应用,文本替换
方法1:sed 's/foo/bar/g' filename
方法2:sed '/foo/ s/foo/bar/g' filename
实例结果分析:sed支持采用正则进行匹配和替换,考虑字符串替换的需求中,不防加上地址以提高速度。实例中通过增加一个判断逻辑,采用“事先匹配”代替“直接替换”,由于sed会保留前一次的正则匹配环境,不会产生冗余的正则匹配,因此方法2具有比方法1更 高的效率
awk不只是一个应用工具,还是一种语法和程序结构类似于C语言的高级编程语言,可以用来开发包括数学运算,字符串处理等运算功能完善的awk脚本程序。awk的执行模式也是基于这样一个循环:先从输入中获取一条记录,然后根据pattern真假决定是否执行action,pattern是对数值运算或文本匹配结果的逻辑判断,action即是由awk的编程语言定义支持的各种操作程序,awk支持用正则用以进行字符串匹配操作。
awk的效率体现在其类似于C语言的高效的主体程序结。awk采用了yacc的yyparse对awk脚本进行解析并形成node结点树,再由采用了c语言编写并且编译完成的awk主体程序树进行递归遍历。这种执行方式,使得awk既有解释程序的便捷,又有编译程序的效率。
前边的实例已经涉及采用awk进行高效的数值计算和文本分析。这里需要着重介绍的是awk的特色数据结构:哈希数组,也称关联数组。哈希数组中的每个单元包括二个元素:单元键(key)及单元值(values)。哈希结构的效益体现在以较小的内存空间实现大的数据空间上的数据存放,节省了数据占存空间;同时哈希数组中的数据访问是随机访问,不需要遍历而直接通过哈希函数直接访问数组单元取值,节省了数据查询时间。
实例 :哈希应用
需求:分析apace日志,获取访问量较大的前十个IP地址
方法: awk ‘{ips[$1]++;}END{for(ip in ips)print ip,ips[ip]}’ |sort –nk2|head -10
实例结果分析:该apace日志首列保存ip信息。能过awk对日志进行一次遍历,即实现了IP信息的获取,同时采用了哈希结构,对ip进行了累计。