分享

awk简明教程

 击碎星辰 2010-07-27

1. awk简介
2. awk命令格式和选项
    2.1. awk的语法有两种形式
   
2.2. 命令选项

3. 模式和操作
    3.1. 模式
   
3.2. 操作

4. awk的环境变量
5. awk
运算符
6. 记录和域
    6.1. 记录
   
6.2.
   
6.3. 域分隔符

7. gawk专用正则表达式元字符
8. POSIX
字符集
9. 匹配操作符(~)
10.
比较表达式
11.
范围模板
12. 一个验证passwd
文件有效性的例子
13.
几个实例
14. awk编程
     14.1. 变量
    
14.2. BEGIN模块
     
14.3. END模块
    
14.4. 重定向和管道
    
14.5. 条件语句
    
14.6. 循环
    
14.7. 数组
    
14.8. awk的内建函数

15. How-to




正文


1. awk简介
      awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出 (屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。下面介绍的awk是以GUN的gawk为例的,在 linux系统中已把awk链接到gawk,所以下面全部以awk进行介绍。



2. awk命令格式和选项
      2.1. awk的语法有两种形式

awk [options] 'script' var=value file(s)

awk [options] -f scriptfile var=value file(s)

      2.2. 命令选项

-F fs or --field-separator fs
指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。

-v var=value or --asign var=value
赋值一个用户定义变量。

-f scripfile or --file scriptfile
从脚本文件中读取awk命令。

-mf nnn and -mr nnn
对nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。

-W compact or --compat, -W traditional or --traditional
在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。

-W copyleft or --copyleft, -W copyright or --copyright
打印简短的版权信息。

-W help or --help, -W usage or --usage
打印全部awk选项和每个选项的简短说明。

-W lint or --lint
打印不能向传统unix平台移植的结构的警告。

-W lint-old or --lint-old
打印关于不能向传统unix平台移植的结构的警告。

-W posix
打开兼容模式。但有以下限制,不识别:\x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符**和**=不能代替^和^=;fflush无效。

-W re-interval or --re-inerval
允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]。

-W source program-text or --source program-text
使用program-text作为源代码,可与-f命令混用。

-W version or --version
打印bug报告信息的版本。



3. 模式和操作
       awk脚本是由模式和操作组成的:
pattern {action} 如$ awk '/root/' test,或$ awk '$3 < 100' test

      两者是可选的,如果没有模式,则action应用到全部记录,如果没有action,则输出匹配全部记录。默认情况下,每一个输入行都是一条记录,但用户可通过RS变量指定不同的分隔符进行分隔。

     3.1. 模式
     模式可以是以下任意一个:
     /正则表达式/:使用通配符的扩展集。
     关系表达式:可以用下面运算符表中的关系运算符进行操作,可以是字符串或数字的比较,如$2>%1选择第二个字段比第一个字段长的行。
     模式匹配表达式:用运算符~(匹配)和~!(不匹配)。
     模式,模式:指定一个行的范围。该语法不能包括BEGIN和END模式。
     BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。
     END:让用户在最后一条输入记录被读取之后发生的动作。
   3.2. 操作
    操作由一人或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内。主要有四部份:
    变量或数组赋值
    输出命令
    内置函数
    控制流命令

4. awk的环境变量
Table 1. awk的环境变量

 

变量 描述
$n 当前记录的第n个字段,字段间由FS分隔。
$0 完整的输入记录。
ARGC 命令行参数的数目。
ARGIND 命令行中当前文件的位置(从0开始算)。
ARGV 包含命令行参数的数组。
CONVFMT 数字转换格式(默认值为%.6g)
ENVIRON 环境变量关联数组。
ERRNO 最后一个系统错误的描述。
FIELDWIDTHS 字段宽度列表(用空格键分隔)。
FILENAME 当前文件名。
FNR 同NR,但相对于当前文件。
FS 字段分隔符(默认是任何空格)。
IGNORECASE 如果为真,则进行忽略大小写的匹配。
NF 当前记录中的字段数。
NR 当前记录数。
OFMT 数字的输出格式(默认值是%.6g)。
OFS 输出字段分隔符(默认值是一个空格)。
ORS 输出记录分隔符(默认值是一个换行符)。
RLENGTH 由match函数所匹配的字符串的长度。
RS 记录分隔符(默认是一个换行符)。
RSTART 由match函数所匹配的字符串的第一个位置。
SUBSEP 数组下标分隔符(默认值是\034)。

 


5. awk运算符
Table 2. 运算符

 

运算符 描述
= += -= *= /= %= ^= **= 赋值
: C条件表达式
|| 逻辑或
&& 逻辑与
~ ~! 匹配正则表达式和不匹配正则表达式
< <= > >= != == 关系运算符
空格 连接
+ - 加,减
* / & 乘,除与求余
+ - ! 一元加,减和逻辑非
^ *** 求幂
++ -- 增加或减少,作为前缀或后缀
$ 字段引用
in 数组成员

 


6. 记录和域
   6.1. 记录
     awk把每一个以换行符结束的行称为一个记录。
     记录分隔符:默认的输入和输出的分隔符都是回车,保存在内建变量ORS和RS中。
     $0变量:它指的是整条记录。如$ awk '{print $0}' test将输出test文件中的所有记录。
     变量NR:一个计数器,每处理完一条记录,NR的值就增加1。如$ awk '{print NR,$0}' test将输出test文件中所有记录,并在记录前显示记录号。

  6.2.
     记录中每个单词称做“域”,默认情况下以空格或tab分隔。awk可跟踪域的个数,并在内建变量NF中保存该值。如$ awk '{print $1,$3}' test将打印test文件中第一和第三个以空格分开的列(域)。
    6.3. 域分隔符
     内建变量FS保存输入域分隔符的值,默认是空格或tab。我们可以通过-F命令行选项修改FS的值。如$ awk -F: '{print $1,$5}' test将打印以冒号为分隔符的第一,第五列的内容。
     可以同时使用多个域分隔符,这时应该把分隔符写成放到方括号中,如$awk -F'[:\t]' '{print $1,$3}' test,表示以空格、冒号和tab作为分隔符。
     输出域的分隔符默认是一个空格,保存在OFS中。如$ awk -F: '{print $1,$5}' test,$1和$5间的逗号就是OFS的值。
7. gawk专用正则表达式元字符
     一般通用的元字符集就不讲了,可参考我的Sed和Grep学习笔记。以下几个是gawk专用的,不适合unix版本的awk。
\Y
匹配一个单词开头或者末尾的空字符串。
\B
匹配单词内的空字符串。
\<
匹配一个单词的开头的空字符串,锚定开始。
\>
匹配一个单词的末尾的空字符串,锚定末尾。
\w
匹配一个字母数字组成的单词。
\W
匹配一个非字母数字组成的单词。
\‘
匹配字符串开头的一个空字符串。
\'
匹配字符串末尾的一个空字符串。

8. POSIX字符集
待完善
9. 匹配操作符(~)
用来在记录或者域内匹配正则表达式。如$ awk '$1 ~/^root/' test将显示test文件第一列中以root开头的行。
10. 比较表达式

 

conditional expression1 ? expression2: expression3

 

例如:

 

$ awk '{max = {$1 > $3} ? $1: $3: print max}' test

 

如果第一个域大于第三个域,$1就赋值给max,否则$3就赋值给max。

 

$ awk '$1 + $2 < 100' test

 

如果第一和第二个域相加大于100,则打印这些行。

 

$ awk '$1 > 5 && $2 < 10' test

 

如果第一个域大于5,并且第二个域小于10,则打印这些行。
11. 范围模板
范围模板匹配从第一个模板的第一次出现到第二个模板的第一次出现之间所有行。如果有一个模板没出现,则匹配到开头或末尾。如$ awk '/root/,/mysql/' test将显示root第一次出现到mysql第一次出现之间的所有行。
12. 一个验证passwd文件有效性的例子

 

$ cat /etc/passwd | awk -F: '\
NF != 7{\
printf("line %d,does not have 7 fields:%s\n",NR,$0)}\
$1 !~ /[A-Za-z0-9]/{printf("line %d,non alpha and numeric user id:%d: %s\n,NR,$0)}\
$2 == "*" {printf("line %d, no password: %s\n",NR,$0)}'

 

cat把结果输出给awk,awk把域之间的分隔符设为冒号。
如果域的数量(NF)不等于7,就执行下面的程序。
printf打印字符串"line ?? does not have 7 fields",并显示该条记录。
如果第一个域没有包含任何字母和数字,printf打印“no alpha and numeric user id" ,并显示记录数和记录。
如果第二个域是一个星号,就打印字符串“no passwd”,紧跟着显示记录数和记录本身。
13. 几个实例
打印所有以模式no或so开头的行。

 

$ awk '/^(no|so)/' test

 

如果记录以n或s开头,就打印这个记录。

 

$ awk '/^[ns]/{print $1}' test

 

如果第一个域以两个数字结束就打印这个记录。

 

$ awk '$1 ~/[0-9][0-9]$/(print $1}' test

 

如果第一个或等于100或者第二个域小于50,则打印该行。

 

$ awk '$1 == 100 || $2 < 50' test

 

如果第一个域不等于10就打印该行。

 

$ awk '$1 != 10' test

 

如果记录包含正则表达式test,则第一个域加10并打印出来。

 

$ awk '/test/{print $1 + 10}' test

 

如果第一个域大于5则打印问号后面的表达式值,否则打印冒号后面的表达式值。

 

$ awk '{print ($1 > 5 ? "ok "$1: "error"$1)}' test

 

打印以正则表达式root开头的记录到以正则表达式mysql开头的记录范围内的所有记录。如果找到一个新的正则表达式root开头的记录,则继续打印直到下一个以正则表达式mysql开头的记录为止,或到文件末尾。

 

$ awk '/^root/,/^mysql/' test

 



14. awk编程
14.1. 变量
在awk中,变量不需要定义就可以直接使用,变量类型可以是数字或字符串。
赋值格式:

Variable = expression,如$ awk '$1 ~/test/{count = $2 + $3; print count}' test
上式的作用是,awk先扫描第一个域,一旦test匹配,就把第二个域的值加上第三个域的值,并把结果赋值给变量count,最后打印出来。
      awk可以在命令行中给变量赋值,然后将这个变量传输给awk脚本。如
$ awk -F: -f awkscript month=4 year=2004 test
上式的month和year都是自定义变量,分别被赋值为4和2004。在awk脚本中,这些变量使用起来就象是在脚本中建立的一样。注意,如果参数前面出现test,那么在BEGIN语句中的变量就不能被使用。
      域变量也可被赋值和修改,如

$ awk '{$2 = 100 + $1; print }' test
上式表示,如果第二个域不存在,awk将计算表达式100加$1的值,并将其赋值给$2,如果第二个域存在,则用表达式的值覆盖$2原来的值。再例如:
$ awk '$1 == "root"{$1 ="test";print}' test
如果第一个域的值是“root”,则把它赋值为“test”,注意,字符串一定要用双引号。
      内建变量的使用。变量列表在前面已列出,现在举个例子说明一下。

$ awk -F: '{IGNORECASE=1; $1 == "MARY"{print NR,$1,$2,$NF}'test
把IGNORECASE设为1代表忽略大小写,打印第一个域是mary的记录数、第一个域、第二个域和最后一个域。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多