Linux下Awk详解(转载)
什么是Awk
Awk是一种小巧的编程语言及命令行工具。(其名称得自于它的创始人Alfred Aho、Peter Weinberger 和 Brian Kernighan姓氏的首个字母)。它非常适合服务器上的日志处理,主要是因为Awk可以对文件进行操作,通常以可读文本构建行。
我说它适用于服务器是因为日志文件,转储文件(dump files),或者任意文本格式的服务器终止转储到磁盘都会变得很大,并且在每个服务器你都会拥有大量的这类文件。如果你经历过这样的情境——在没有像Splunk或者其他等价的工具情况下不得不在50个不同的服务器里分析几G的文件,你会觉得去获取和下载所有的这些文件并分析他们是一件很糟糕的事。
我亲身经历过这种情境。当一些Erlang节点将要死掉并留下一个700MB到4GB的崩溃转储文件(crash dump)时,或者当我需要在一个小的个人服务器(叫做VPS)上快速浏览日志,查找一个常规模式时。
在任何情况下,Awk都不仅仅只是用来查找数据的(否则,grep或者ack已经足够使用了)——它同样使你能够处理数据并转换数据。
代码结构
Awk脚本的代码结构很简单,就是一系列的模式(pattern)和行为(action):
# comment
Pattern1{ACTIONS;}
# comment
Pattern2{ACTIONS;}
# comment
Pattern3{ACTIONS;}
# comment
Pattern4{ACTIONS;}
扫描文档的每一行时都必须与每一个模式进行匹配比较,而且一次只匹配一个模式。那么,如果我给出一个包含以下内容的文件:
this is line 1
this is line 2
this is line 1 这行就会与Pattern1进行匹配。如果匹配成功,就会执行ACTIONS。然后this is line 1 会和Pattern2进行匹配。如果匹配失败,它就会跳到Pattern3进行匹配,以此类推。
一旦所有的模式都匹配过了,this is line 2 就会以同样的步骤进行匹配。其他的行也一样,直到读取完整个文件。
简而言之,这就是Awk的运行模式
数据类型
Awk仅有两个主要的数据类型:字符串和数字。即便如此,Awk的字符串和数字还可以相互转换。字符串能够被解释为数字并把它的值转换为数字值。如果字符串不包含数字,它就被转换为0.
它们都可以在你代码里的ACTIONS部分使用 = 操作符给变量赋值。我们可以在任意时刻、任意地方声明和使用变量,也可以使用未初始化的变量,此时他们的默认值是空字符串:“”。
最后,Awk有数组类型,并且它们是动态的一维关联数组。它们的语法是这样的:var[key] = value 。Awk可以模拟多维数组,但无论怎样,这是一个大的技巧(big hack)。
模式
可以使用的模式分为三大类:正则表达式、布尔表达式和特殊模式。
正则表达式和布尔表达式
你使用的Awk正则表达式比较轻量。它们不是Awk下的PCRE(但是gawk可以支持该库——这依赖于具体的实现!请使用 awk–version查看),然而,对于大部分的使用需求已经足够了:
/admin/ {...}# any line that contains 'admin'
/^admin/ {...}# lines that begin with 'admin'
/admin$/ {...}# lines that end with 'admin'
/^[0-9.]+ / {...}# lines beginning with series of numbers and periods
/(POST|PUT|DELETE)/ # lines that contain specific HTTP verbs
注意,模式不能捕获特定的组(groups)使它们在代码的ACTIONS部分执行。模式是专门匹配内容的。
布尔表达式与PHP或者Javascript中的布尔表达式类似。特别的是,在awk中可以使用&&(“与”)、||(“或”)、!(“非”)操作符。你几乎可以在所有类C语言中找到它们的踪迹。它们可以对常规数据进行操作。
与PHP和Javascript更相似的特性是比较操作符,==,它会进行模糊匹配(fuzzy matching)。因此“23”字符串等于23,”23″ == 23 表达式返回true。!= 操作符同样在awk里使用,并且别忘了其他常见的操作符:>,<,>=,和<=。
你同样可以混合使用它们:布尔表达式可以和常规表达式一起使用。 /admin/ || debug == true 这种用法是合法的,并且在遇到包含“admin”单词的行或者debug变量等于true时该表达式就会匹配成功。
注意,如果你有一个特定的字符串或者变量要与正则表达式进行匹配,~ 和!~ 就是你想要的操作符。 这样使用它们:string ~ /regex/ 和 string !~ /regex/。
同样要注意的是,所有的模式都只是可选的。一个包含以下内容的Awk脚本:
{ ACTIONS }
对输入的每一行都将会简单地执行ACTIONS。
特殊的模式
在Awk里有一些特殊的模式,但不是很多。
第一个是BEGIN,它仅在所有的行都输入到文件之前进行匹配。这是你可以初始化你的脚本变量和所有种类的状态的主要地方。
另外一个就是END。就像你可能已经猜到的,它会在所有的输入都被处理完后进行匹配。这使你可以在退出前进行清除工作和一些最后的输出。
最后一类模式,要把它进行归类有点困难。它处于变量和特殊值之间,我们通常称它们为域(Field)。而且名副其实。
域
使用直观的例子能更好地解释域:
# According to the following line
#
# $1 $2 $3
# 00:34:23 GET /foo/bar.html
# _____________ _____________/
# $0
# Hack attempt?
/admin.html$/ && $2 == "DELETE"{
print"Hacker Alert!";
}
域(默认地)由空格分隔。$0 域代表了一整行的字符串。 $1 域是第一块字符串(在任何空格之前), $2 域是后一块,以此类推。
一个有趣的事实(并且是在大多是情况下我们要避免的事情),你可以通过给相应的域赋值来修改相应的行。例如,如果你在一个块里执行 $0 = “HAHA THE LINE IS GONE”,那么现在下一个模式将会对修改后的行进行操作而不是操作原始的行。其他的域变量都类似。
行为
这里有一堆可用的行为(possible actions),但是最常用和最有用的行为(以我的经验来说)是:
{print$0;}# prints $0. In this case, equivalent to 'print' alone
{exit;}# ends the program
{next;}# skips to the next line of input
{a=$1;b=$0}# variable assignment
{c[$1] = $2}# variable assignment (array)
{if(BOOLEAN){ACTION}
elseif(BOOLEAN){ACTION}
else{ACTION}
}
{for(i=1;i<x;i++){ACTION}}
{for(item inc){ACTION}}
这些内容将会成为你的Awk工具箱的主要工具,在你处理日志之类的文件时你可以随意地使用它们。
Awk里的变量都是全局变量。无论你在给定的块里定义什么变量,它对其他的块都是可见的,甚至是对每一行都是可见的。这严重限制了你的Awk脚本大小,不然他们会造成不可维护的可怕结果。请编写尽可能小的脚本。
函数
可以使用下面的语法来调用函数:
{ somecall($2) }
这里有一些有限的内置函数可以使用,所以我可以给出这些函数的通用文档(regular documentation)。
用户定义的函数同样很简单:
# function arguments are call-by-value
functionname(parameter-list){
ACTIONS;# same actions as usual
}
# return is a valid keyword
functionadd1(val){
returnval+1;
}
特殊变量
除了常规变量(全局的,可以在任意地方使用),这里还有一系列特殊的变量,它们的的作用有点像配置条目(configuration entries):
BEGIN{# Can be modified by the user
FS = ",";# Field Separator
RS = "n";# Record Separator (lines)
OFS = " ";# Output Field Separator
ORS = "n";# Output Record Separator (lines)
}
{# Can't be modified by the user
NF# Number of Fields in the current Record (line)
NR# Number of Records seen so far
ARGV / ARGC# Script Arguments
}
我把可修改的变量放在BEGIN里,因为我更喜欢在那重写它们。但是这些变量的重写可以放在脚本的任意地方然后在后面的行里生效。
示例
以上的就是Awk语言的核心内容。我这里没有大量的例子,因为我趋向于使用Awk来完成快速的一次性任务。
不过我依然有一些随身携带的脚本文件,用来处理一些事情和测试。我最喜欢的一个脚本是用来处理Erlang的崩溃转储文件,形如下面的:
=erl_crash_dump:0.3
Tue Nov1802:52:442014
Slogan: init terminating indo_boot()
System version: Erlang/OTP17[erts-6.2][source][64-bit][smp:8:8][async-threads:10][hipe][kernel-poll:false]
Compiled: Fri Sep1903:23:192014
Taints:
Atoms: 12167
=memory
total: 19012936
processes: 4327912
processes_used: 4319928
system: 14685024
atom: 339441
atom_used: 331087
binary: 1367680
code: 8384804
ets: 382552
=hash_table:atom_tab
size: 9643
used: 6949
...
=allocator:instr
optionm: false
options: false
optiont: false
=proc:<0.0.0>
State: Running
Name: init
Spawned as: otp_ring0:start/2
Run queue: 0
Spawned by: []
Started: Tue Nov1802:52:352014
Message queue length: 0
Number of heap fragments: 0
Heap fragment data: 0
Linklist: [<0.3.0>, <0.7.0>, <0.6.0>]
Reductions: 29265
Stack+heap: 1598
OldHeap: 610
Heap unused: 656
OldHeap unused: 468
Memory: 18584
Program counter: 0x00007f42f9566200(init:boot_loop/2 + 64)
CP: 0x0000000000000000(invalid)
=proc:<0.3.0>
State: Waiting
...
=port:#Port<0.0>
Slot: 0
Connected: <0.3.0>
Links: <0.3.0>
Port controls linked-indriver: efile
=port:#Port<0.14>
Slot: 112
Connected: <0.3.0>
...
产生下面的结果:
$awk -fqueue_fun.awk$PATH_TO_DUMP
MESSAGE QUEUE LENGTH: CURRENT FUNCTION
======================================
10641: io:wait_io_mon_reply/2
12646: io:wait_io_mon_reply/2
32991: io:wait_io_mon_reply/2
2183837: io:wait_io_mon_reply/2
730790: io:wait_io_mon_reply/2
80194: io:wait_io_mon_reply/2
...
这是在Erlang进程里运行的函数列表,它们导致了mailboxe变得很庞大。脚本在这:
# Parse Erlang Crash Dumps and correlate mailbox size to the currently running
# function.
#
# Once in the procs section of the dump, all processes are displayed with
# =proc:<0.M.N> followed by a list of their attributes, which include the
# message queue length and the program counter (what code is currently
# executing).
#
# Run as:
#
# $ awk -v threshold=$THRESHOLD -f queue_fun.awk $CRASHDUMP
#
# Where $THRESHOLD is the smallest mailbox you want inspects. Default value
# is 1000.
BEGIN{
if(threshold == ""){
threshold = 1000# default mailbox size
}
procs = 0# are we in the =procs entries?
print"MESSAGE QUEUE LENGTH: CURRENT FUNCTION"
print"======================================"
}
# Only bother with the =proc: entries. Anything else is useless.
procs == 0 && /^=proc/ {procs = 1}# entering the =procs entries
procs == 1 && /^=/ && !/^=proc/ {exit0}# we're done
# Message queue length: 1210
# 1 2 3 4
/^Message queue length: / && $4 >= threshold{flag=1;ct=$4}
/^Message queue length: / && $4 < threshold{flag=0}
# Program counter: 0x00007f5fb8cb2238 (io:wait_io_mon_reply/2 + 56)
# 1 2 3 4 5 6
flag == 1 && /^Program counter: / {print ct":",substr($4,2)}
你跟上思路没?如果跟上了,你已经了解了Awk。恭喜!
Linux下Awk详解(转载)的更多相关文章
- linux sar 命令详解(转载)
linux sar 命令详解 2013-04-01 11:05 [小 大] 来源: 开源中国社区 评论: 0 分享至: 百度权重查询 词库网 网站监控 服务器监控 SEO监控 手机游戏 iPhone游 ...
- 【转载】Linux下makefile详解--跟我一起写 Makefile
概述 —— 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makef ...
- Linux 下crontab 详解转
http://yaksayoo.blog.51cto.com/510938/162062 Linux计划任务工具cron用法详解 linux下大名鼎鼎的计划任务工具crontab的使用介绍baidu. ...
- 12 Linux下crontab详解
1. 概述: crond是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具,并且会自动启动crond进 ...
- Linux下crontab详解
1.crond介绍 crond是Linux下的任务调度命令,让系统定期执行指定程序.crond命令每分钟都会检查是否有要执行的工作,若有要执行的程序便会自动执行. linux下任务调度工作主要分两类: ...
- linux screen 命令详解(转载)
转载于:http://www.cnblogs.com/mchina/archive/2013/01/30/2880680.html 一.背景 系统管理员经常需要SSH 或者telent 远程登录到Li ...
- linux中awk 详解
一.awk简介 awk是一个非常好用的数据处理工具,相对于sed常常作用于一整个行的处理,awk则比较倾向于一行当中分成数个[字段]处理,因此,awk相当适合处理小型的数据数据处理.awk是一种报表生 ...
- linux sort 命令详解(转载)
转载:http://www.cnblogs.com/51linux/archive/2012/05/23/2515299.html#3374576 sort是在Linux里非常常用的一个命令,管排序的 ...
- Linux下lampp详解 (转)
重要文件解释: ProFTPD:一个Unix平台上或是类Unix平台上(如Linux, FreeBSD等)的FTP服务器程序,它是在自由软件基金会的版权声明(GPL)下开发.发布的免费软件,可以随意修 ...
随机推荐
- 市面上常见的javaEE WEB服务软件
常见的市面上web服务软件 Tomcat:轻量级的WEB应用程序服务器(开源),开源组织Apache的产品.免费的.支持部分的JavaEE规范.(servlet.jsp.jdbc,但ejb, rmi不 ...
- Spring mvc web.xml中 urlpatten的配置问题
在使用spring mvc 是我们会配置spring 的DispatcherServlet作为请求的转发器. <servlet> <servlet-name>spring< ...
- [小北De编程手记] : Lesson 05 玩转 xUnit.Net 之 从Assert谈UT框架实践
这一篇,本文会介绍一下基本的断言概念,但重点会放在企业级单元测试的相关功能上面.下面来跟大家分享一下xUnit.Net的断言,主要涉及到以下内容: 关于断言的概念 xUnit.Net常用的断言 关于单 ...
- 商业银行在CNAPS体系中对各种交易的处理
简单来讲,商业银行在CNAPS体系中, 一)行内的交易 由各个银行的行内业务系统来自行解决信息流和资金流问题: 二)跨行的交易分渠道处理 柜台和网银等渠道,商业银行直接直连央行的大小额以及超级网银来解 ...
- Tabio – 轻松,高效的管理 Chrome 标签页
Tabio 是一个 Chrome 扩展,旨在简化大量浏览器标签页的管理.它提供的搜索功能允许您快速.轻松地找到您需要的选项卡.Tabio 便于组织你的标签,简单的拖拽排序.您也可以使用输入.删除和箭头 ...
- HTML中input标签的alt属性和title属性的比较
经常用到这两个属性,但是一直没有总结他们的区别.现在我对他们两个的用法做一下总结: 相同点:他们都会飘出一个小浮层,显示文本内容. 不同点: 1.alt只能是元素的属性,而title即可以是元素的属性 ...
- svn服务端和eclipse配合使用
今天弄了个svn服务器来做项目的版本控制,讲讲我做的步骤吧 1.安装svn服务端 2.下载subclipse插件 3.将subclipse插件安装到eclipse上,点击Install New Sof ...
- JavaScript学习笔记-基础语法、类型、变量
基础语法.类型.变量 非数字值的判断方法:(因为Infinity和NaN他们不等于任何值,包括自身) 1.用x != x ,当x为NaN时才返回true; 2.用isNaN(x) ,当x为NaN或 ...
- .NET web开发之WebApi初试水
前几天看了.NET的EF(Entity Framework),发现居然有这么先进的东西,只要操作几个类就可以完成数据库的增删查改,而且可以用数据库直接导出类(DB First).也可以用类来生成数据库 ...
- iOS 使用AFNetworking遇到错误 Request failed: unacceptable content-type: text/html
错误日志: Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacc ...