众所周知Linux有文本处理三剑客:grep, sed, awk

 

grep: 文本过滤器

sed: 行编辑器

awk: 报告生成器

之前我们已经介绍过grep的用法了,今天就来为大家介绍一个非常强大的工具awk

 

 

 

一、AWK的基本用法

awk [options] 'program' file file ...

awk [options] 'PATTERN{action}' file file ...

 

1、awk的输出

print item1, item2,...

    要点:

         (1) 各项目之间使用逗号分隔,而输出时则使用输出分隔符分隔;

         (2) 输出的各item可以字符串或数值、当前记录的字段、变量或awk的表达式;数值会被隐式转换为字符串后输出;

         (3) print后面item如果省略,相当于print $0;输出空白,使用pirnt "";

 

2、awk的变量

    内置变量,自定义变量

 

2.1 内置变量

    FS: 输入时的字段分隔符

【示例1】输出/etc/passwd文件中的用户名和shell类型

awk 'BEGIN{FS=":"}{print $1,$7}' /etc/passwd

    RS: 输出行分隔符

    OFS:  输出时的字段分隔符;

    ORS:  输出时的行分隔符;

    NF:字段数

    NR:行数;所有文件的一并计数;

    FNR:行数;各文件分别计数;

    ARGV:数组,保存命令本身这个字符,awk '{print $0}' 1.txt 2.txt,意味着ARGV[0]保存awk,

    ARGC: 保存awk命令中参数的个数;

    FILENAME: awk正在处理的当前文件的名称;


   2.2 可自定义变量

        -v 变量名=变量值

 

       变量名区分字符大小写;


3awkprintf命令

    命令的使用格式:printf format, item1, item2,...

 

       要点:

          (1) 要指定format

          (2) 不会自动换行;如需换行则需要给出\n

          (3) format用于为后面的每个item指定其输出格式;

 

           format格式的指示符都%开头,后跟一个字符:

               %c: 显示字符的ASCII码;

               %d, %i: 十进制整数;

               %e, %E: 科学计数法显示数值;

               %f: 显示浮点数;

               %g, %G: 以科学计数法格式或浮点数格式显示数值;

               %s: 显示字符串;

               %u: 显示无符号整数;

               %%: 显示%自身;

 

          修饰符:

             #:显示宽度

             -:左对齐

             +:显示数值的符号

             .#: 取值精度

 

4awk输出重定向

        print items > output-file

        print items >> output-file

        print items | command

 

    特殊文件描述符:

        /dev/stdin: 标准输入

        /dev/stdout: 标准输出

        /dev/stderr: 错误输出

 

5awk的操作符

 

     算术操作符:

          +-*/**(次方)、%(取余)、-x:负值、+x:转换为数值

     赋值操作符:

          =+=-=/=%=^=**=++--

注:如果模式自身是=号,要写为/=/

 

    比较操作符:

          <<=>>===!=

          ~:模式匹配,左边的字符串能够被右边的模式所匹配为真,否则为假;

          !~:

 

    逻辑操作符:

          &&: 与

          ||:或

 

     条件表达式:

          selector?if-true-expression:if-false-expression

【示例2】/etc/passwd文件中id小于500显示为系统用户,大于500为普通用户

awk -F: '{$3>=500?utype="common user":utype="admin or system user";print $1,"is",utype}' /etc/passwd

     函数调用:

           function_name(argu1,argu2)


6、模式

      (1) Regexp: 格式为/PATTERN/

                  仅处理被/PATTERN/匹配到的行;

      (2) Expression: 表达式,其结果为非0或非空字符串时满足条件;

                      仅处理满足条件的行;

      (3) Ranges: 行范围,此前地址定界,startline, endline

                  仅处理范围内的行

      (4) BEGIN/END: 特殊模式,仅在awk命令的program运行之前(BEGIN)或运行之后(END)执行一次;

      (5) Empty:空模式,匹配任意行;

 

7、常用的action

      (1) Expressions           表达式

      (2) Control statements      控制语句

      (3) Compound statements   复合语句

      (4) input statements        输入语句

      (5) output statements       输出语句

 

8、控制语句



   8.1 if-else

       格式:if (condition) {then body} else {else body}

【示例3/etc/passwd文件中id小于500显示为系统用户,大于500为普通用户

awk -F: '{if ($3>=500) {print $1,"is a common user"} else {print $1, "is an admin or system user"}}' /etc/passwd

【示例4】显示inittab文件中字段大于等于8的行

awk '{if (NF>=8) {print}}' /etc/inittab


   8.2 while

       格式:while (condition) {while body}

【示例5】显示inittab文件中字段数为奇数的行

awk '{i=1; while (i<=NF){printf "%s ",$i;i+=2};print ""}' /etc/inittab

【示例6】显示inittab文件中字段数大于6的行

awk '{i=1; while (i<=NF){if (length($i)>=6) {print $i}; i++}}' /etc/inittab

注:length()函数:取字符串的长度



   8.3 do-while循环

       格式:do {do-while body} while (condition)

 

   8.4 for循环

       格式:for (variable assignment; condition; iteration process) {for body}

【示例7】显示inittab文件中字段数为奇数的行

awk '{for (i=1;i<=NF;i+=2){printf "%s ",$i};print ""}' /etc/inittab

【示例8】显示inittab文件中字段数大于6的行

awk '{for (i=1;i<=NF;i++){if (length($i)>=6) print $i}}' /etc/inittab

        for循环可用来遍历数组元素:

           语法:for (i in array) {for body}

 

   8.5 case语句

       语法:switch (expression) {case VALUE or /RGEEXP/: statement1;... default: stementN}

 

   8.6 循环控制

       break

       continue

 

   8.7 next

       提前结束对本行的处理进而进入下一行的处理;

【示例9】显示passwd文件中id为奇数的用户名和id

awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd

【示例10】显示passwd文件中奇数行的用户名

awk -F: '{if(NR%2==0) next; print NR,$1}' /etc/passwd



9、数组

 

   关联数组:

        array[index-expression]

 

    index-expression: 可以使用任意字符串如果某数组元素事先不存在,那么在引用时,awk会自动创建此元素并将其初始化为空串;因此,要判断某数组是否存在某元素,必须使用“index in array”这种格式;

 

         A[first]="hello awk"

         print A[second]

 

       要遍历数组中的每一个元素,需要使用如下特殊结构:

                   for (var in array) {for body}

 

       其var会遍历array的索引;

 

          state[LISTEN]++

          state[ESTABLISHED]++

netstat -tan | awk '/^tcp/{++state[$NF]}END{for (s in state) {print s,state[s]}}'
 
awk '{ip[$1]++}END{for (i in ip) {print i,ip[i]}}' /var/log/httpd/access_log

        删除数组元素:

            delete array[index]

 

10awk的内置函数

 

        split(string,array[,fieldsep[,seps]])

    功能:将string表示的字符串以fieldsep为分隔符进行切片,并切片后的结果保存至array为名的数组中;数组下标从1开始;

 

         root:x:0:0::/root:/bin/bash

         user[1]="root", user[2]

 

    此函数有返回值,返回值为切片后的元素的个数

netstat -tn | awk '/^tcp/{lens=split($5,client,":");ip[client[lens-1]]++}END{for (i in ip) print i,ip[i]}'

          

           length(string)

               功能:返回给定字串的长度

 

           substr(string,start[,length])

               功能:从string中取子串,从start为起始位置为取length长度的子串;