文本处理三剑客----awk详细介绍

awk命令格式:

awk [ options ] 'program' file ...

program: [/PATTERN/]{ACTION statement; ...}
PATTERN部分:决定动作语句何时触发以及通过什么事件来触发;
BEGIN, END

ACTION statement:对数据进行特定的处理,通常放置在{}中;
print, printf

awk基本概念:

分隔符:(输入分隔符和输出分隔符),

记录:由换行符进行分隔的数据中一行,称为一条记录,用$0来保存整条记录

字段:经过分隔符分隔之后的每一个数据分段,都称为一个字段(Field)

awk工作原理:

1.首先,执行BEGIN{ACTION statement;...}语句块中的语句;

2.其次,从文件中或着标准输入读取一行,根据PATTERN的匹配结果执行后面的ACTION语句块中的内容;然后逐行重复该过程已完成数据处理,直到数据全部被读取完毕;
3.最后,在所有的语句块都执行完成之后,退出awk进程之前,执行END{ACTION statement;...}语句块中的语句;

注意:
1) BEGIN语句块在awk开始处理数据内容之前就被执行;通常用于生成表头;此语句块是可选语句块;
2) END语句块在处理完所有的数据之后,才会被执行;通常用于数据汇总;此语句块是可选语句块;
3) PATTERN语句块中的通用命令是最重要的部分,因此PATTERN语句块不能省略,但其中的ACTION可以省略,如果省略,则默认执行print动作,即:显示数据的各行;
4) awk在执行PATTERN语句块时,默认循环遍历数据中的各个记录;

常用选项:

-f:从指定的文件中加载program语句块,而不是通过命令行给出相关的程序内容;

-F:指定字段的输入分隔符;默认是空白字符;

-v, --assign var=val:用于声明自定义变量并为变量赋值;

awk的常用用法:

1)变量--内建变量

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

OFS:输出字段分隔符,默认为空白字段

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

RS【The  input  Record  separator】:输入记录(行)分隔符,默认为换行符

ORS【The  output  Record  separator】:输出记录(行)分隔符,默认为换行符

示例:awk  -v RS=":"   -v   ORS="#"   '{print  $0}'   /etc/passwd

NF【The  number  of  record】:每行中字段的总数

示例:awk  -F ":"  '{print  NF}'   /etc/passwd      --显示passwd文件中每行字段的个数

           awk  -F ":"  ‘{print  $NF}’   /etc/passwd     ---显示passwd文件中最后一个字段

NR:【the total number of  input  records 】行的总数;如果处理一个文件,可以将NR的值作为文件中各行的行号

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

FNR:对于不同的文件分别统计其行的数量;

示例:]# awk '{print FNR}' /etc/fstab /etc/issue

FILENAME:当前正在被处理的文件的文件名

示例:# awk 'END{print FILENAME}'   /etc/fstab 

2)变量--自定义变量

定义方式:-v var_name=value  变量名大小写敏感

示例:awk -v var='hello' -F: '{print $1"," var}' /etc/passwd

常用的Action:

1)print:以标准格式输出结果

格式:print item1,item2,...

注意点:各个item之间是由逗号隔开;输出的各item可以是字符串,可以是数字,可以是当前记录中的字段,可以是变量,可以是awk的表达式 

示例:awk '{print $1,$3,$NF}' /etc/issue

2)printf:以特定的格式输出结果

格式:printf "FORMAT" item1,item2,..

注意点:必须给出合适的输出格式;默认不会自动换行,如果想要在输出结果中显示换行,需要显示给出换行控制符号,即\nFORMAT中需要为后面的每一个item单独指定一个格式化符号;

常用的FORMAT:%number+字母 标识这么多个数字的字符以%字母格式显示 例:%20s

    %c:以ASCII码表中的内容显示字符信息;
    %d, %i:显示十进制整数;
    %e, %E:以科学计数法来显示数字;浮点类型;
    %f, %F:显示十进制数字的浮点形式;
    %g, %G:以科学计数法显示浮点数字;
    %u:显示无符号十进制数;
    %s:显示字符串;
    %x, %X:显示无符号的十六进制整数;
    %%:显示%;

  修饰符

    #[.#]:第一个数字用来控制显示宽度;第二个数字表示小数点的精度;
    如:%5s, $8.3f

    -:表示采用左对齐方式显示;默认是右对齐;
    +:显示数字的正负符号;

示例:# awk -F: '{printf "%20s:%-+5d\n",$1,$3}' /etc/passwd

操作符:

算术运算操作符:

    双目运算必须用两个数字进行计算:(x+y, x-y, x*y, x/y, x^y, x%y)

    单目运算符:(+x;-x)

示例:awk -F : 'END{print 100^2}' /etc/passwd

字符串操作符:

无任何操作时,即字符串连接操作

赋值操作符:=, +=, -=, *=, /=, ^=, %=, ++, --

比较操作符:==, !=, >, >=, <, <=

示例:awk -F : '$3>=1000 print $1}' /etc/passwd

模式匹配操作符:

~:操作符左侧的字符串是否能够被右侧的PATTERN所匹配

!~:操作符左侧的字符串是否能够不被右侧的PATTERN所匹配

示例:awk -F : '$NF~/bash/{print $0}' /etc/passwd

逻辑运算操作符:&&;||;!

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

条件表达式:

selector(condition)?if-true-expression:if-false-expression

示例:awk -F: '{$3>=1000?usertype="Common User":usertype="SuperUser or Sysuser";print$1,":",usertype}' /etc/passwd

root: SuperUser or Sysuser
bin: SuperUser or Sysuser
daemon: SuperUser or Sysuser
adm: SuperUser or Sysuser
lp: SuperUser or Sysuser

。。。

PATTERN部分:

1)empty:空模式,不加分区域的处理文件的每一行

2) [!]/REGEXP/:仅处理【不】能被pattern匹配到的行

示例:awk -F:  '/^r/{print $0}' /etc/passwd

3)关系表达式  

      $3>1000

      $NF~/bash/

示例:awk -F : '$3>=1000 print $1}' /etc/passwd

awk  -F ":" '$3>100{ print$1,":",$7}'

示例:

4)行域:行范围

   关系表达式的逻辑运算:FNR>=10&&FNR<==20

示例:awk 'NR>=15&&NR<=20{print NR,$0}'   /etc/passwd

   /REGEXP1/,/REGEXP2/:从被REGEXP1匹配的行开始,直到被REGEXP2匹配的行结束,这期间的所有行;凡是属于此类的匹配结果,有多少组就显示多少组;

示例:awk -F: '/^r/,/^a/{print NR,$0}' /etc/passwd

BEGIN/AND模式:

BEGIN{}:仅在开始处理文件中的第一行文本数据之前执行一次的语句块;多用于输出特定格式的表头信息;

示例:awk -F: 'BEGIN{printf "%20s %10s %20s\n","USERNAME","USERID","SHELL"}NR>=15&&NR<=20{printf "%20s %10s %20s\n",$1,$3,$7}' /etc/passwd

END{}模式:仅在文本处理完成但awk命令尚未退出时执行一次的语句块;多用于数据信息的汇总;

示例:# awk -F: 'BEGIN{printf "%20s %10s %20s\n","USERNAME","USERID","SHELL"}NR>=15&&NR<=20{printf "%20s %10s %20s\n",$1,$3,$7}END{print "------------------------------------------------------------------\n",NR " users"}' /etc/passwd

注意:BEGIN语句块,PATTERN语句块和END语句块的顺序,通常是BEGIN{}PATTERN{}END{}

常用的ACTIONS

1)表达式

2)组合语句

3)输入语句

4)输出语句

5)控制语句  

控制语句:

if...else:if  (condition) statement [else statement]

while循环:while(condition)statement

do...while语句:do statement while (condition)

for循环:

   for(expr1;expr2;expr3) statement

   for (var  in array)  statement

break和continue语句:

   break

   continue

exit [expression]

switch...case语句:switch (expresion)  { case value|regex : statement ... [ default: statement ] }

next语句:next

1)if ...else语法

  语法:if (condition) statement [ else statement ]  一般用于对awk取得的整行或某个字段做条件判断;

  示例: #awk -F: '{if($3>=1000){print "CommonUser:",$1}else{print "Sysuser:",$1}}' /etc/passwd

             # awk '/^[^#]/{if(NF==6){print}}'  /etc/fstab

2)while循环

  语法:while (condition)statement :对一行内的多个字段逐一做相同或类似的操作处理时使用;对数组中的各数组元素做遍历时使用

  特点:条件为真,则进入循环,一旦条件为假,则退出循环

  示例:判断字符串长度:awk '{i=1;while(i<=NF){print $i,length($i);i++}}'   testfile

3)do...while语句

  语法:do  statement while (condition)

  意义:与while循环相同,但statement语句至少被执行一次

4)for循环

  语法:for  (expr1,expr2,expr3) statement

        expr1:变量初赋值

        expr2:循环条件判断

        expr3:变量值修正方法

   示例:awk '{for(i=1;i<=NF;i++){print $i,length($i)}}'   testfile

5)switch...case语句:用于对字符串进行比较

       switch (expression) { case value|regex:statement;case value2|regex2:statement;... [ default: statement ] }

6)break和continue语句:使用场景是多个字段间做循环时的循环控制方式

      示例:awk '{for(i=1;i<=NF;i++){if(length($i)<5){continue}else{print $i,length($i)}}}' testfile

7)next语句

      在awk处理数据时,提前结束对当前行的处理,而直接开始处理下一行;

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

数组--Array

    用户自定义的数组,一般使用关联数组:array_name[index_expression]

    注意:index_expression可以使用任意的字符串,但字符串必须放在双引号内;

    示例:awk 'BEGIN{name["leader"]="zhangsan";name["mem1"]="lisi";name["mem2"]="bob";print "Leader:",name["leader"],"Member:",name["mem1"],name["mem2"]}'

               awk 'BEGIN{name["leader"]="zhangsan";name["mem1"]="lisi";name["mem2"]="bob";for(i in name){print name[i]}}'

               查看当前系统上所有服务不同的TCP状态的连接数量的统计。

               netstat -nalt | awk '/^tcp\>/{state[$NF]++}END{for(stat in state){printf "%15s: %-10d\n",stat,state[stat]}}'

猜你喜欢

转载自www.cnblogs.com/wzylhj/p/12156721.html