AWK

awk:报告生成器,格式化文本输出

gawk:模式扫描和处理语言

    基本语法:

      options:选项

      program:awk的语言

      var=value:赋值给var

      file:参数

           awk [options] 'program' var=value file...

           awk [options] -f programfile var=value file...

           awk [options] 'BEGIN{action} pattern{ action;...}END{action;...}' file.. 

           

选项:

     -F 指定分隔符

     -v var=value:自定义变量


awk语言

    基本格式:awk [options] 'program' file....

    program:pattern{action statements;...}

        pattern和action:

            pattern部分决定动作语句何时触发及触发事件

            BEGIN:文件处理之前就执行一个动作

            END:当所有文件处理结束后执行一个动作

            action statements对数据进行处理,放在{}内指明

            print,printf

分隔符、域和记录

        awk执行时,由分隔符分隔的字段(域)标记$1,$2...$n成为域标识;$0为所有域

        文件的每一行称为记录,也可以用别的作为记录的分隔符

        省略action,默认执行print $0

awk工作原理

    第一步:如果有BEGIN{action;...}优先执行BEGIN

    第二步:从命令的执行结果或者文件读取一行,然后执行pattern{action;...},逐行处理

    第三步:执行END{action;....}


awk

item=要打印的字符

  print格式:print item1,item2,...

注意:

   (1)逗号分隔符

   (2)输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式

   (3)如省略item,相当于print $0


awk变量

    field 域,字段,列column,属性(一个意思)

    行,记录,record(一个意思)

变量:内置和自定义变量

     使用变量时,需添加-v选项


FS:字段的分隔符,默认为空白字符

awk -v FS=':' '{print $1,FS,$2}' passwd (指定FS变量值为:打印passwd文件的第一列和第二列,逗号是作为空白符的)


OFS:输出分隔符的定义

awk -v OFS="+" '{print $1,$2}' passwd(指定OFS变量值为+,打印passwd文件的第一列和第二列,输出分隔符是+)


RS:指定分开记录的分隔符

记录:默认回车换行算一条记录

    awk -v RS=";" '{print $2}' f1.txt中的值为 aa bb cc;ee 

                                                       ff oo;xx 

                                                       yy zz (指定RS变量值为;打印f1.txt文件的第二列,结果为bb ff yy)

ORS:指定记录输出的分隔符

awk -v RS=" " -v ORS="###" '{print}' passwd(默认以回车换行区分每条记录,ORS指定区分每条记录的分隔符)


NF:字段个数

    awk -F: '{print NF}' passwd(逐行处理,显示的全是7)

    awk -F: '{print $NF}' passwd(逐行处理,显示第7列的数据,因为NF是7)

    awk -F: '{print $(NF-1)}' passwd(逐行处理,显示7-1列的数据)


NR:记录号

awk '{print NR,$0}' passwd(逐行处理,每一行都打印,并且显示每一行的行号)


FNR:文件分别计数

awk '{print FNR,$0}' /etc/fstab /etc/issue(两个文件分别显示所有行并且显示行号)


FILENAME:当前文件名

awk '{print FNR,FILENAME,$0}' /etc/fstab /etc/issue(两个文件分别显示所有行并且在前面显示文件名称)


ARGC:参数个数

awk '{print ARGC}' /etc/fstab /etc/issue(查看awk的参数)


ARGV:数组,显示命令行awk算第一个参数,跳过print部分,后续为第二个参数,第三个参数

awk '{print ARGV[0]}' /etc/fstab /etc/issue


print中也可以定义变量

awk的-f选项可以读取文件,文件中写入的是'{print}'等一系列数据


printf命令

格式化输出:printf "FORMAT",item1,item2,....

      (1)必须指定FORMAT

      (2)不会自动换行,需要显示给出换行控制符,\n

      (3)FORMAT中需要分别为后面每个item指定格式符

格式符:与item一一对应

      %c:显示字符的ASCII码

      %d,%i:显示十进制整数

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

      %f:显示为浮点数

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

      %s:显示字符串

   %u:无符号整数

      %%:显示%自身

修饰符:

      #[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f

      -:左对齐(默认右对齐) %-15s(前面空出15个宽度并且左对齐显示)

      +:显示数值的正负符号%+d


操作符:

    x+y, x-y, x*y, x/y, x^y, x%y

    -x: 转换为负数 

    +x: 转换为数值

赋值操作符: 

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

++, -- 

比较操作符: 

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

模式匹配符: 

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

可以使用扩展的正则表达式,""中写正则表达式,或者//中写正则表达式

例子:awk –F: '$0 ~ /^root/' /etc/passwd 匹配文件中以root开头的行

     awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd (打印匹配第三个字段大于0并且第三个字段小于1000)

     awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd (打印匹配第三个字段等于0或者第三个字段大于1000)

     awk -F: '!($3==0){print $1}' /etc/passwd (打印第三个字段不等于0的行)

     awk -F: '!($3>=500){print $3}' /etc/passwd (打印第三个字段不等于500的字段的行)

awk当中变量为""为假,为0的时候为假,有值则为真

条件表达式(三目表达式:用三个表达式,分别用?:分开分成三段)

例子:awk -F: '{$3>=1000?usertype="common user":usertype="sysuser";printf "%-15s:%-30s %d \n",usertype,$1,$3}'


awk PATTERN

PATTERN:就是花括号前面的部分

(1)如果没有指定:空模式,匹配每一行

(2)/正则表达式/

(3)关系表达式,结果为真才会被处理

真:结果为非0值,非空字符串

加:结果为空字符串或0值

(4)line ranges:行范围

   '/条件/,/条件/' 第一个条件必须要匹配,第二个条件没有的话则会匹配到结尾

(5)BEGIN/END模式

   BEGIN{}:处理文件之前处理一次

   END{}:在文件处理完成之后处理一次


awk action

常用的action分类

(1)算数,表达式

(2)if,while等

(3)组合语句就是?:分开的

(4)输入语句

(5)输出:print

if语句

语法:if(表达式){执行的操作;....}[else 执行操作]


while循环:当字段个数过多并且都要执行的时候可以使用

语法:while(表达式){执行的操作;...}

条件"真",进入循环;条件"假"退出循环


do-while循环

语法:do{执行操作;}while(表达式)

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


next:

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


awk数组

关联数组:array[下标自定义]

(1)可使用任意字符串;字符串要用双引号括起来

awk '!arr[$0]++' 文件名(去掉重复行操作)


遍历数组.

for(var in array){for-body}

awk '{IP[$1]}END{for(i in IP)print i,IP[i]}' /var/log/access_log 统计IP地址的连接次数


awk函数

数值处理:

    rand():返回0和1之间的一个随机数,但是如果单独打印rand()是不能生成随机数的与srand()函数结合使用,默认生成的浮点数,生成整数如下

例子:awk 'BEGIN{srand();print int(rand()*100)}':生成随机整数

字符串处理:

    length("指定字符串"):返回指定字符串长度

    sub(r,s,要处理的字符串):对要处理的字符串进行搜索r表示修改的字符串,s是修改后的字符串,只替代第一个匹配到的

    gsub:是将匹配到的全部替换

    split(s,arry,r):对字符串s进行切割,使用r作为分隔符,将切割后的结果保存到arry的数组中,成为了数组的值


自定义函数

格式:

    function "name" (参数1,参数2,.....相当于shell的$1,$2,$3....){

                      代码

                      return "表达式"

                   }

调用的参数是实际参数,命名的时候是形式参数;实际参数和形式参数的名称可以不同,但数量要相同


使用system调用bash命令

例子:awk BEGIN'{system("hostname")}'

如果是awk中定义的变量awk要用system的echo调用的话将命令加入到双引号中