Linux的文本三剑客(grep sed awk) —— awk的介绍

一、三剑客简介

     grep: 文本过滤工具, (grep,egrep,fgrep)  文本搜索工具,根据用户指定的“模式”对目标文件逐步进行匹配检查,打印匹配到的行。

     sed: 文本编辑工具,实现数据的替换,删除,增加,选取等(以行为单位进行处理)。

     awk: 文本报告生成器,以字段为单位进行处理(把一行的数据分割,然后进行处理)。

     本文只介绍awk。

awk的介绍

    1. awk的简介

     awk不仅是linux系统中的一个命令,还是一种编程语言,可以用来处理数据和生成报告(excel)。处理的数据可以是一个或多个文件,可以是来自标准输入,也可以通过管道获取标准输入,awk可以在命令行上直接编辑命令进行操作,也可以编写成awk程序来进行更为复杂的运用。

     awk的应用里最重要的一个功能就是计数,而数组在awk里最大的作用就是去重复。

     2. awk的格式

    awk指令是由模式,动作,或者模式和动作的组合组成。

    awk  [options] 'pattern{print} ' file

    模式既pattern,可以类似理解成sed的模式匹配,可以由表达式组成,也可以是两个正斜杠之间的正则表达式。比如NR==1,这就是模式,可以把他理解为一个条件。     动作即action,是由在大括号里面的一条或多条语句组成,语句之间使用分号隔开。

image.png

image.png

   注意:

     pattern和{action}需要用单引号引起来,防止shell作解释。

     pattern是可选的。如果不指定,awk将处理输入文件中的所有记录。如果指定一个模式,awk则只处理匹配指定的模式的记录。

    {action}为awk命令,可以是但个命令,也可以多个命令。

    整个action(包括里面的所有命令)都必须放在{  }内。

    action必须被{ }包裹,没有被{ }包裹的就是patern

    file要处理的目标文件

     3. awk工作原理

      awk 程序通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成。

      第一步:执行BEGIN{action;… }语句块中的语句。

      第二步:从文件或标准输入读取一行,然后执行pattern{ action;… }语句块,逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
      第三步:当读至输入流末尾时,执行END{action;…}语句块。

      BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。

      END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。

     pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。

    4. 记录与字段

   awk对每个要处理的输入数据认为都是具有格式和结构的,而不仅仅是一堆字符串。默认情况下,每一行内容都是一条记录,并以换行符分隔(\n)结束。

    简单来说:     记录  =  行

                     字段,域  =  列

    小结:

    RS  记录分隔符,表示每行的结束标志
    NR  行号(记录号)
    FS  字段分隔符,每列的分隔标志或结束标志
    NF  就是每行有多少列,每个记录中字段的数量
    $  符号表示取某个列(字段),$1$2$NF
    NF  表示记录中的区域(列)数量,$NF取最后一个列(区域。)
    FS(-F)字段(列)分隔符,-F(FS)“:”<==>‘BEGIN{FS=':'}’
    NR  行号
    分隔符==>结束标识

  5. awk变量

    1,内置变量

FS:输入字段分隔符

 awk -v FS=':' '{print $1,$3}' /etc/passwd

     先找一个文件/etc/passwd作为参数,这样可查看命令的结果。

image.png

image.png

OFS:输出字段分隔符

awk -v FS=':' -v OFS=':' '{print $1,$3}' /etc/passwd

image.png

RS:输入的记录分隔符

awk -v FS="." -v RS=" " '{print $1}' chen

image.png

ORS:输出的记录分隔符

awk -v FS="." -v RS=" " -v ORS="#" '{print $1}' chen

image.png

NF:字段的数量

awk -F" " '{print NF}' /etc/fstab

image.png

image.png

NR:记录号

awk '{print NR,$0}' /etc/fstab

image.png

FNR:各文件分别计数,行号

awk '{print FNR}' /etc/fstab /etc/inittab

image.png

FILENAME:当前文件名

awk '{print FILENAME}’ /etc/fstab

image.png

ARGC:命令行参数的个数

awk '{print ARGC}' /etc/fstab  /etc/shadow

image.png

ARGV:数组,保存的是命令行所给定的各参数

awk 'BEGIN {print ARGV[2]}'  /etc/fstab /etc/inittab

image.png

打印命令行的最后一个参数

awk 'BEGIN {print ARGV[ARGC-1]}'  /etc/fstab /etc/inittab /etc/haha hi hello

image.png

  2,自定义变量

    (1) -v var=value
    (2) 在program中直接定义

image.png

image.png

image.png

image.png

    6. 输出命令

   1,输出命令:print

    用法:print item1,item2,...

           item:字符串,用引号引用;

           变量:显示变量的值,可以直接使用变量的名进行引用;

           数值:不加引号

    要点:

       (1)各item之间使用逗号分隔;输出的分隔符默认为空白字符;

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

       (3)print后的item省略时,相当于运行"print $0" ,用于输出整行;

       (4)输出空白字符:print " "

 2,格式化输出:printf

    用法:printf “FORMAT”, item1, item2, ...

    (1)必须指定FORMAT;
    (2) 不会自动换行,需要显式给出换行控制符,\n;
    (3)FORMAT中需要分别为后面每个item指定格式符;

   格式符:与item一一对应
    %c: 显示字符的ASCII码
    %d, %i: 显示十进制整数
    %e, %E:显示科学计数法数值
    %f:显示为浮点数
    %g, %G:以科学计数法或浮点形式显示数值
    %s:显示字符串
    %u:无符号整数

    %%: 显示%自身

   举例:

awk -F: '{printf "Username:%s UID:%s\n",$1,$3}' /etc/passwd

image.png


awk -F: '{printf "Username:%-15s UID:%s\n",$1,$3}' /etc/passwd

image.png

awk -F: 'BEGIN{printf "%.d %.2f\n",1.73333,3.1111}'

image.png

   修饰符:

    #[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f
    -: 左对齐(默认右对齐) %-15s
    +:显示数值的正负符号 %+d

   7. awk操作符

   1, 算术操作符:
   x+y, x-y, x*y, x/y, x^y, x%y
  -x: 转换为负数

  +x: 转换为数值

awk 'BEGIN{print 2^5}

image.png

    2, 字符串操作符:没有符号的操作符,字符串连接

    3, 赋值操作符:

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

   ++, --

awk 'BEGIN{print i++;print i}'
awk 'BEGIN{print ++i;print i}'

image.png

    4, 比较操作符:

   ==, !=, >, >=, <, <=

awk -v FS=: '$3 == 0 {print $0}' /etc/passwd

image.png

    5, 模式匹配符:

    ~:左边是否和右边匹配包含
    !~:是否不匹配


awk '$0 ~ "^root" {print $0}' /etc/passwd

image.png

    6, 逻辑操作符:与&&,或||,非!

awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd

image.png    

    7, 函数调用: function_name(argu1, argu2, ...)
    8, 条件表达式(三目表达式):
selector?if-true-expression:if-false-expression

   9,关系表达式
   为非0时,即为真,才处理
   为0或为空时,不处理

    !0=1  !Num=0  (Num为任意非0的值)

   举例:

df |awk -v FS=% '$0 ~ "/dev/sd" {print $1}'|awk '$NF>=10 {printf "DevName:%-10s Used:%s%%\n",$1,$5}'

image.png

   8. PATTERN

     PATTERN:根据pattern条件,过滤匹配的行,再做处理
     (1)如果未指定:空模式,匹配每一行
     (2) /regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来
awk '/^UUID/{print $1}' /etc/fstab

awk '!/^UUID/{print $1}' /etc/fstab

image.png

    (3) relational expression: 关系表达式,结果为“真”才会被处理
    真:结果为非0值,非空字符串
    假:结果为空字符串或0值

    (4) 行范围

cat /boot/grub/grub.conf |awk '/default/,/hidden/' 匹配以'/default/开始,以/hidden/结束'的范围

image.png

    (5) BEGIN/END模式
    BEGIN{ }:仅在开始处理文件中的文本之前执行一次
    END{ }:仅在文本处理完成之后执行

    9. 控制语句

   1,if-else

   语法:

     if(condition){statement;…}[else statement]
     if(condition1){statement1}else if(condition2){statement2}
     else{statement3}
   使用场景:

     对awk取得的整行或某个字段做条件判断

awk -v FS=: '{if($3>=1000){usertype="Common User"}else{usertype="Sys User"}printf "UserName:%-15s Type:%s\n",$1,usertype}' /etc/passwd

image.png

   2,while循环

  语法:

      while(condition){statement;…}

    条件“真”,进入循环;条件“假”,退出循环
 使用场景:
     对一行内的多个字段逐一类似处理时使用
     对数组中的各元素逐一处理时使用

echo {1..10} |awk '{n=1;while(n<=NF){if($n%2==0){print $n,"oushuo"}eelse {print $n,"jishu"};n++}}'

image.png


    3,do-while循环

  语法:do {statement;…}while(condition)

  意义:无论真假,至少执行一次循环体

    4,for循环
  语法:for(expr1;expr2;expr3) {statement;…}
  常见用法:
     for(variable assignment;condition;iteration process)
     {for-body}
  特殊用法:能够遍历数组中的元素
  语法:for(var in array) {for-body}

    5, switch语句

  语法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; ...; default: statementn}

   6, break和continue

    break[n]:退出当前循环,n为数字,用于指定推出几层循环;

    continue:提前结束本轮循环而进入下一轮;

awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i};print sum}'

image.png

awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==1)continue;sum+=i};print sum}'

image.png

  7,next:提前结束对本行处理而直接进入下一行处理(awk自身循环)

image.png

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

image.png

    10. 数组

    关联数组:array[index-expression]
     index-expression:
    (1) 可使用任意字符串;字符串要使用双引号括起来
    (2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”;要判断数组中是否存在某元素,要使用“index in array”格式进行遍历。

     数组遍历:

   若要遍历数组中的每个元素,要使用for循环
   for(var in array) {for-body}
    注意:

    var会遍历array的每个索引

image.png

     11. 函数 

       函数分为内建函数和用户自定义函数

        1,内建函数

        数值处理rand():返回0至1之间的一个随机数;

awk 'BEGIN{srand();print int(rand()*10000)}'

image.png

        字符串处理:

         length([s]):返回指定的字符串的长度。

awk 'BEGIN{print length("hello")

image.png

         sub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹配的内容替换为s。

echo "2018:08:29 10:08:30" |awk 'sub(/:/,"-",$1)'

image.png

         gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容。

echo "2018:08:08 08:08:08" |awk 'gsub(/:/,"-",$1)'  匹配第一字段
echo "2018:08:08 08:08:08" |awk 'gsub(/:/,"-",$0)'  匹配所有

image.png

image.png

         split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中。

netstat -tan

image.png

netstat -tan |awk '/^tcp\>/&& !($5 ~ "*") {split($5,ip,":");count[ip[1]]++}ENcount[ip[1]]++}END{for(i in count){print i,count[i]}}'

image.png

           注意:awk的数组下标从开始编号。

         substr(s,i[,n]):从s所表示的字符串中取出字串。取法:从i表示的位置开始,取n个字符。

三、总结

记住三个命令的运用形式
     grep    '字符'       文件
     sed     '命令'       文件
     awk    '条件{命令}'   文件

单引号内就是正则表达式的用法

重复一遍:单引号内一定是正则表达式!



猜你喜欢

转载自blog.51cto.com/13869720/2166210