首页 > 代码库 > 三剑客之gawk

三剑客之gawk

gawk:

  • gawk - pattern scanning and processing language: 模块扫描及处理语言
  • AWK: Aho,Weinberger,Kernighan 三个设计人名字
  • GNU awk :gawk
  • awk :功能遍历文件每一行并且对每一行做单独处理.
  • awk也称报告生成器,格式化文本输出工具
  • 基本用法 :
  •      gawk [options] `program` FILE..
  •      program:PATTERN{ACTTION STATEMENTS}动作语句
  •      语句之间用分号分隔
  • 选项:
  •     -F:指明输入时用到的字段分隔符;
  •          [root@C6 ~]# awk -F : ‘{print $1,$2}‘ /etc/passwd
  •           root x
  •           bin x
  •     -v var=value :自定义变量;
  • print:

  •   print item1, item2,...
  •  
  •        [root@C6 ~]# awk ‘{print $1,$2}‘ /etc/passwd
  •        root:x:0:0:root:/root:/bin/bash
  •        bin:x:1:1:bin:/bin:/sbin/nologin
  • 要点: 
  •    1 . 逗号分隔;
  •    2 . 输出的各item可以字符串,也可以是数值;当前记录的字段,变量或awk的表达式;      
  •        [root@C6 ~]# awk -F : ‘{print "username:"$1,$2}‘              /etc/passwd
  •        username:root x
  •        username:bin x
  •       在awk中变量不适用引号 ,否则会被当做字符串输出
  •        [root@C6 ~]# awk -F : ‘{print "username:$1"}‘ /etc/passwd
  •        username:$1
  •        username:$1
  •       如省略item,相当于print $0;
  •       [root@C6 ~]# awk -F : ‘{print}‘ /etc/passwd
  •        root:x:0:0:root:/root:/bin/bash
  •        bin:x:1:1:bin:/bin:/sbin/nologin
  • 变量
  •     2.1 内键变量
  •        FS:input field seperator,默认为空白字符;
  •         指明以什么分隔
  •         [root@C6 ~]# awk -v FS=‘:‘ ‘{print $1}‘ /etc/passwd
  •         root
  •         bin
  •         相当于 -F
  •        OFS:output  field seperator, 默认为空白字符       
  • 自定义分隔符:
  •         [root@C6 ~]# awk -v FS=‘:‘ -v OFS=‘:‘ ‘{print $1,$3}‘ /etc/passwd
  •          root:0
  •          bin:1
  •        每一个-v用来定义一个变量
  •        RS input record seperator,指明输入时的换行符
  •         以空白为换行符
  •         [root@C6 ~]# awk -v RS=‘ ‘ ‘{print}‘ /etc/passwd
  •        ORS output record seperaor, 指明输出时的换行符
  •         指明#号为输出换行符
  •         [root@C6 ~]# awk -v RS=‘ ‘ -v ORS=‘#‘ ‘{print}‘ /etc/passwd
  • NF :number of field ,字段数量
  •       [root@C6 ~]# awk ‘{print NF}‘ /etc/fstab
  •        0
  •        1
  •        2
  •        10
  •      awk 引用内部变量时不需要使用$
  •        {print NF} , {print  $NF}
  • NR :number of record  文件的行数,对行进行统计       
  •         [root@C6 ~]# awk ‘{print NR}‘ /etc/fstab
  •         1
  •         2
  •         3 
  •       
  •  FNR :各文件分别计数;行数
  •       awk ‘{print FNR}‘ /etc/fstab /etc/passwd
  •  FILENAME : 当前文件名
  •      [root@C6 ~]# awk ‘{print FILENAME}‘ /etc/fstab
  •       /etc/fstab
  •        etc/fstab
 
  •     ARGC:命令行参数的个数
  •     [root@C6 ~]# awk ‘BEGIN{print ARGC}‘ /etc/fstab
  •      2
 
  •  ARGV:数组,保存的是命令行所给定的各参数;
  •         [root@C6 ~]# awk ‘BEGIN{print ARGV[0]}‘ /etc/fstab
  •         awk
  •  自定义变量

  •        1 -v var=value
  •        变量名区分字符大小写;
  •        awk -v aa="bb" ‘BEGIN{ PRINT aa}‘
  •         [root@C6 ~]# awk -v aa="bb" ‘{print aa}‘ /etc/passwd
  •         bb
  •         bb
  •        2 在program中直接定义
  •        [root@C6 ~]# awk  ‘BEGIN{aa="bb";print aa}‘
  •         bb
  • printf命令

  •    格式化输出: printf FORMAT格式符, itrm1,item2,....
  •     1 . FORMAT 必须给出;
  •     2 . 不会自动换行,需要显示给出换行控制符,\n
  •     3 . FORMAT中需要分别尾喉面的每个item指定一个格式化符号;
 
  • 格式符:任何格式符后所对应的条目会被套在格式符上显示item不会单独显示
  •        %c :显示字符的ASCII码;
  •        %d,%i:显示十进制整数;
  •     %e,%E: 科学计数法数值显示;
  •        %f; 显示为浮点数
  •        %g,%G:以科学计数法或浮点形式显示数值;
  •        %s:显示字符串
  •        %u:无符号整数
  •        %%: 显示%自身:
  •    默认不会显示换行符
 
  • 示例
  •       [root@C6 ~]# awk -F: ‘{printf "username:%s\n",$1}‘ /etc/passwd
  •       username:root
  •       username:bin
  •       username:daemon
  •      [root@C6 ~]# awk -F: ‘{printf "username:%s,UID: %d\n",$1,$3}‘ /etc/passwd
  •       username:root,UID: 0
  •       username:bin,UID: 1
  •       username:daemon,UID: 2
 
  •  修饰符:
  •         #[.#]:第一个数字控制显示的宽度,第二个#表示小数点后的精度; 
  •                 %3.1f
  •           -:左对齐
  •           +:显示数值的符号
  • 右对齐:
  •           [root@C6 ~]# awk -F: ‘{printf "username:%15s,UID:           %d\n",$1,$3}‘ /etc/passwd
  •           username:           root,UID: 0
  •           username:            bin,UID: 1
  •           username:         daemon,UID: 2
  • 左对齐:
  •           [root@C6 ~]# awk -F: ‘{printf "username:%-15s:UID: %d\n",$1,$3}‘ /etc/passwd
  •           username:root           :UID: 0
  •           username:bin            :UID: 1
  •           username:daemon         :UID: 2
  •           username:adm            :UID: 3
  • 操作符
  •         算数操作符
  •        x+y, x-y,x*y,x/y,x^y,x%y
  •       -x  
  •       +x:把一个字符串转换为数值
  • 字符串操作符: 没有符号的操作符,字符串连接
  • 赋值操作符:
  •     =,+=,-=, *=,/=, %=, ^= ,++ ,--
  •  比较操作符:
  •     >, >=,<, <=, !=,==
  • 模式匹配符:
  •     &&
  •     ||
  •     !
  •  函数调用:
  •    function_name(argue1 ....)
  • 条件表达式:

  •   selector?if-ture-expression:if-false-expression
  • 示例:
  • 找出/etc/passwd/ 系统用户和普通用户 
  •    [root@C6 ~]# awk -F: ‘{$3 >=900?Utype="common user":Utype="sysuser ro dime"; printf "%15s:%-s\n",$1,Utype,$3}‘ /etc/passwd
  •            root:sysuser ro dime
  •             bin:sysuser ro dime
  •          daemon:sysuser ro dime
  •             adm:sysuser ro dime
  •              lp:sysuser ro dime
  • pattern 

  •    1 empty:空模式 , 匹配每一行;
  •    2 /regular  expression/:仅处理能够被此处的模式匹配到的行 
  •           [root@C6 ~]# awk ‘/UUID/{print $1}‘ /etc/fstab
  •           UUID=ab5839fc-cf8d-48ad-9067-49385b8645ca
  •           UUID=aac33902-12f8-4adb-b680-d96dab832d30
  •           UUID=b6781c5f-6bb6-4add-b181-5b664db4c358
  •           UUID=b272d4c8-df03-4e0c-95f9-5aa3c83443ee
  •           [root@C6 ~]# awk ‘!/UUID/{print $1}‘ /etc/fstab
  •  
  •           #
  •           #
  •           #
  •           #
  •           #
  •           #
  •           #
  •    3 relational expression ;关系表达式,结果有"真" 有"假" :结果为"真"才会被处理;
  •        真:结果为非0值,非空字符串;
  • 显示/etc/passwd中uid大于等于500的用户或这说普通用户
  •      [root@C6 ~]# awk -F: ‘$3>=500{print $1,$3}‘ /etc/passwd
  •       nfsnobody 65534
  •       user 500
  •       logstash 501
  • 显示/etc/passwd中以/bin/bash结尾用户名和的行
  •   awk -F: ‘$NF~"/bin/bash"{print $1,$NF}‘ /etc/passwd
  •   [root@C6 ~]# awk -F: ‘$NF=="/bin/bash"{print $1,$NF}‘ /etc/passwd
  •   root /bin/bash
  •   user /bin/bash
  •   logstash /bin/bash
  •  line ranges:行范围

  •     startline, endline: /pat1,/pat2/   
  • 对/etc/passwd中第十行到二十行处理
  •  [root@C6 ~]# awk -F: ‘10,20{print $1}‘ /etc/passwd
  •      root
  •      bin
  •      daemon
  •   注意: 不支持直接给出数字的格式
  •  [root@C6 ~]# awk -F: ‘(NR>=2&&NR<=10){print $1} ‘ /etc/passwd
  •      bin
  •      daemon
  •      adm
  •      lp
  • BEGIN/END模式

  •  NEGIN{} :仅在开始处理文件中的文本之前执行一次;
  •  END{} :紧在文本处理完成之后执行一次;
  •      
  •  [root@C6 ~]# awk -F: ‘BEGIN{print"   username   usid \n------------"} {print $1,$2}‘ /etc/passwd
  •    username   usid
  • ------------
  • root x
  • bin x
  • daemon x
  •  
  • [root@C6 ~]# awk -F: ‘BEGIN{print"   username   usid \n------------"} {print $1,$2}END{print  "***********" }‘ /etc/passwd
  • 常用的action

  •   1 . Expressions 表达式
  •   2 . Control statements : if while 等;条件控制语句
  •   3 . Compound statements: 组合语句;
  •   4 . input statements   :输入语句 
  •   5 . output  statements :输出语句
  • 控制语句

  •      if(condition) {statements}但分支if语句
  •      if (condition) {statements} else {statments} 双分支if语句
  •      while (condition) {statements}   
  •      do {staements} while (condition)  无论条件真假都会执行一次
  •      for (expr1;expr2;expr3) {statements}
  •      break
  •      continue
  • if else

  •            
  •   语法:if (condition)statement [else statement]如果只有多个语句需要加花括号
  • 使用场景:对awk取得的正行或某个字段做条件判断
  •        找出 /etc/passwd 中系统用户和普通用户
  •       [root@C6 ~]# awk -F: ‘{if($3>=500) print $1,$3}‘ /etc/passwd
  •       nfsnobody 65534
  •       user 500
  •       logstash 501
  •       [root@C6 ~]# awk -F: ‘{if($3<=500){printf "sysuser:%15s\n",$1}else{printf "common user: %15s\n",$1}}‘ /etc/passwd
  •       sysuser:           root
  •       sysuser:            bin
  •      
  • 显示/etc/passwd中以/bin/bash结尾用户名,及shell.
  •      [root@C6 ~]# awk -F: ‘{if($NF=="/bin/bash")print $1,$7‘ /etc/passwd
  •      root
  •      user
  •      logstash
  • 如果某一行的字段数大于五个则显示否则不显示
  •      [root@C6 ~]# awk ‘{if(NF>5)print }‘ /etc/fstab
  •      # Created by anaconda on Tue Apr 25 23:44:59 2017
  •      # Accessible filesystems, by reference, are maintained 
  • 查看dev设备使用率大于%20的显示出来
  •      [root@C6 ~]# df -h | awk -F[%] ‘/^\/dev/{print $1}‘|awk ‘{if($NF>=5)print $NF}‘
  •      8
  • while循环

  • 语法: while(condition) statement
  •  条件"真",进入循环:条件"假"退出循环
  •  使用场景: 对一行内的多个字段逐一类似处理时使用:对数组中的个元素逐一处理时使用:
  • 示例
  •  对/etc/grub.conf/initrd开头行做字段字符个数统计
  •       [root@C6 test]# awk ‘/^[[:space:]]*initrd/{i=1;while(i<=NF) {print $i,length($i); i++}}‘ /etc/grub.conf
  •      initrd 6
  •      /initramfs-2.6.32-642.el6.x86_64.img 36
  • 对/etc/grub.conf/initrd开头行做字段字符个数统计,并只显示字段大于等于4的行
  •      [root@C6 ~]# awk ‘/^[[:space:]]*initrd/{i=1;while(i<=NF) {if(length($i)>=4) print $i,length($i); i++}}‘ /etc/grub.conf
  •      initrd 6
  •      /initramfs-2.6.32-642.el6.x86_64.img 36
  •  for循环 

  •      语法 :for(expr1;expr2;expr3...) statement()
  •    
  •       for(variable assignment; condition;iteration process) {for-body}
  • 示例:
  • 对/etc/grub.conf/initrd开头行做字段字符个数统计,并只显示字段大于8的行
  • [root@C6 ~]# awk ‘/^[[:space:]]*initrd/{for(i=1;i<=NF;i++) {if(length($i)>8) print $i,length($i)}}‘ /etc/grub.conf
  • /initramfs-2.6.32-642.el6.x86_64.img 36
  • 特殊用法:
  •      能够遍历数组中的元素;
  •      语法:for(var in array) {for-body}
  •   next :

  •     控制awk提前结束本行的处理而直接进入下一行
  •     打印出/etc/passwd中ID为偶数的用户
  •      [root@C6 test]# awk -F: ‘{if($3%2!=0) next; print $1,$3}‘ /etc/passwd
  •      root 0
  •      daemon 2
  •      lp 4
  •       分析  如果用第三列%2后不等于0 则直接跳过 打印 第一列 和第三列
  •  array

  •   关联数组

  •      array [index-expression]
  •      index-expression
  •      1 . 可使用任意字符串;字符串要是用双引号
  •      2 . 如果某数组元素实现不存在,在引用时,awk会自动创建元素,并将其值初始化为"空串"
  •      要判断数组中是否存在某元素,要是用"index in array"格式进行;
  •      weekdays[mon]=Monday\
  •      [root@C6 test]# awk      ‘BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}‘
  •      Monday
  •  若要遍历数组中的每个元素,要是用for循环
  •       [root@C6 test]# awk ‘BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays){print weekdays[i]}}‘
  •      Monday
  •      Tuesday
  • 注意:var会遍历array的每个索引;
  •    统计ss -tan每一种状态个出现多少次
  •       root@C6 test]# netstat -tan|awk ‘/^tcp\>/{state[$NF]++}END{for(i in state) {print i,state[i]}}‘
  •      ESTABLISHED 1
  •      LISTEN 9
  • 统计http日志文件每个用户访问的次数
  •       [root@C6 test]# awk ‘{ip[$1]++}END{for(i in ip) {print i,ip[i]}}‘ /var/log/httpd/access_log
  •      192.168.174.1 17
  • 练习:
  • 1 . 统计 /etc/fstab 文件中每个文件系统类型出现的次数;
  •      [root@C6 test]# awk ‘ /^UUID/{fs[$3]++}END{for (i in fs) {print i,fs[i]}}‘ /etc/fstab
  •      swap 1
  •      ext4 3
  • 2 . 统计指定文件中每个单词出现的次数
  •     [root@C6 ~]#  awk ‘ {for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}‘ /etc/fstab  /etc/fstab
  •      mount(8) 2
  •      Accessible 2    
  • 函数

  •    内置函数
  •    数值处理:
  •          rand() :返回0和1之间一个随机数;
  •          [root@C6 ~]# awk ‘BEGIN{print rand()}‘
  •          0.237788
  •          只有第一次取的是随机值
  •    字符串处理:
  •           length([s]): 返回指定字符串的长度;
  •           sub (r,s,[t]): 以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;
  •           gsub (r,s,[t]) :表示全局替换
  •           split(s,a[,r]):以r为分隔符切割字符s,并将切割后的结果保存至a所在数组中

 

三剑客之gawk