首页 » 系统工具 » 正文

20分钟 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):

  1. # comment
  2. Pattern1 { ACTIONS; }
  3. # comment
  4. Pattern2 { ACTIONS; }
  5. # comment
  6. Pattern3 { ACTIONS; }
  7. # comment
  8. Pattern4 { ACTIONS; }

扫描文档的每一行时都必须与每一个模式进行匹配比较,而且一次只匹配一个模式。那么,如果我给出一个包含以下内容的文件:

  1. this is line 1
  2. 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查看),然而,对于大部分的使用需求已经足够了:

  1. /admin/ { } # any line that contains ‘admin’
  2. /^admin/ { } # lines that begin with ‘admin’
  3. /admin$/ { } # lines that end with ‘admin’
  4. /^[09.]+ / { } # lines beginning with series of numbers and periods
  5. /(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。

发表评论