简述awk命令及用法

简述awk命令及用法

简述awk命令及用法

AWK是一种处理文本文件的语言,是一个强大的文本分析工具。

语法

awk [options]'program' {filenames}

参数

-F:指明输入时用到的字段分隔符,默认是空格符
-v var=value: 自定义变量

program

program: PATTERN{ACTION STATEMENTS}
         语句之间用分号分隔
  • print
    • 格式 :print item1,item2,….
      $0:表示整个当前行
      $1:每行第一个字段
      NR:number of record, 总行数;
      NF:number of field,字段数量
          {print NF}:打印每行的字段
          {print $NF}:打印第NF个字段值(最后一个字段的值)
      FNR:单个数据文件处理的行数
      \t:制表符
      \n:换行符
      

    • 实例
      • F & $0
        #输出整行,awk {print} /etc/passwd = awk '{print $0}' /etc/passwd
        ~]# awk {print} /etc/passwd
        ~]# awk '{print $0}' /etc/passwd
        root:x:0:0:root:/root:/bin/bash
        bin:x:1:1:bin:/bin:/sbin/nologin
        daemon:x:2:2:daemon:/sbin:/sbin/nologin
        
        #":"为分格符输出第一个字符
        ~]# awk -F":" '{print $1}'  /etc/passwd
        root
        bin
        daemon
        
        #$1与$3相连输出,不分隔
        ~]# awk -F":" '{print $1 $3}'  /etc/passwd 
        root0
        bin1
        daemon2
        
        #多了一个逗号,$1与$3使用空白分格分隔
        ~]# awk -F":" '{print $1,$3}'  /etc/passwd
        root 0
        bin 1
        daemon 2
        
        #$1与$3使用分格符分隔,自定义分隔符
        ~]# awk -F":" '{print $1 "," $3}'  /etc/passwd
        root,0
        bin,1
        daemon,2        
        ~]# awk -F":" '{print $1 "-" $3}'  /etc/passwd
        root-0
        bin-1
        daemon-2    
        
        #自定义输出内容
        ~]# awk -F":" '{print "Username:" $1" \t Uid:" $3 }' /etc/passwd
        Username:root    Uid:0
        Username:bin     Uid:1
        
      • NF
        #显示每行有多少字段
        ~]# awk -F: '{print NF}' /etc/passwd  
        7
        7
        7
        
        #将每行第NF个字段的值打印出来
         ~]# awk -F: '{print $NF}' /etc/passwd
        /bin/bash
        /sbin/nologin
        /sbin/nologin
        
        #只输出字段数=7的行
        ~]# awk -F":" 'NF==7 {print }' /etc/passwd
        root:x:0:0:root:/root:/bin/bash
        bin:x:1:1:bin:/bin:/sbin/nologin
        daemon:x:2:2:daemon:/sbin:/sbin/nologin
        
        #输出字段数>2的行
        ~]# awk -F":" 'NF>2{print $0}' /etc/passwd
        root:x:0:0:root:/root:/bin/bash
        bin:x:1:1:bin:/bin:/sbin/nologin
        daemon:x:2:2:daemon:/sbin:/sbin/nologin
        
      • NR
        #输出每行的行号
        localhost ~]# awk '{print NR,$0}' /etc/passwd 
        1 root:x:0:0:root:/root:/bin/bash
        2 bin:x:1:1:bin:/bin:/sbin/nologin
        3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
        
        #显示第5行
        localhost ~]# awk -F: 'NR==5{print}'  /etc/passwd 
        lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
        
        #显示5行以后的数据,并在前面显示行号
        localhost ~]# awk -F: 'NR>5{print NR ,$0}'  /etc/passwd 
        6 sync:x:5:0:sync:/sbin:/bin/sync
        7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
        8 halt:x:7:0:halt:/sbin:/sbin/halt
        .....
        
        #显示5行和第8行,并在前面显示行号
        localhost ~]#awk -F: 'NR==5 || NR == 8 {print NR ,$0}'  /etc/passwd 
        5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
        8 halt:x:7:0:halt:/sbin:/sbin/halt
        
      • FNR&NR
        localhost tmp]# cat data3
        hello
        hello
        hello
        localhost tmp]#  awk '{print $0 ,"\t""FNR="FNR,"NR="NR}' data3 data3
        hello   FNR=1 NR=1
        hello   FNR=2 NR=2
        hello   FNR=3 NR=3
        hello   FNR=1 NR=4
        hello   FNR=2 NR=5
        hello   FNR=3 NR=6
        
  • 格式化打印printf
    printf FORMAT, item1, item2, ...
        (1) FORMAT必须给出; 
        (2) 不会自动换行,需要显式给出换行控制符,\n
        (3) FORMAT中需要分别为后面的每个item指定一个格式化符号;
    
    • 格式符:
      %c: 显示字符的ASCII码;
      %d, %i: 显示十进制整数;
      %e, %E: 科学计数法数值显示;
      %f:显示为浮点数;
      %g, %G:以科学计数法或浮点形式显示数值;
      %s:显示字符串;
      %u:无符号整数;
      %%: 显示%自身;
      
    • 修饰符
      #[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度;
      -: 左对齐
      +:显示数值的符号
      
    • 说明
      (1). 可以在"%"和字母之间插进数字表示最大场宽。 
              例如:%3d 表示输出3位整型数, 不够3位右对齐。 
              %9.2f 表示输出场宽为9的浮点数, 其中小数位为2, 整数位为6,小数点占一位, 不够9位右对齐。 
              %8s 表示输出8个字符的字符串, 不够8个字符右对齐。 
      如果字符串的长度、或整型数位数超过说明的场宽, 将按其实际长度输出.但对浮点数, 若整数部分位数超过了说明的整数位宽度, 将按实际整数位输出;若小数部分位数超过了说明的小数位宽度, 则按说明的宽度以四舍五入输出.
      另外, 若想在输出值前加一些0, 就应在场宽项前加个0。 
              例如: %04d 表示在输出一个小于4位的数值时, 将在前面补0使其总宽度为4位。 
      如果用浮点数表示字符或整型量的输出格式, 小数点后的数字代表最大宽度,小数点前的数字代表最小宽度。 
              例如: %6.9s 表示显示一个长度不小于6且不大于9的字符串。若大于9, 则第9个字符以后的内容将被删除。
      
      (2). 可以在"%"和字母之间加小写字母l, 表示输出的是长型数。 
              例如: %ld 表示输出long整数 
                  %lf 表示输出double浮点数 
      
      (3). 可以控制输出左对齐或右对齐, 即在"%"和字母之间加入一个"-" 号可说明输出为左对齐, 否则为右对齐。 
              例如: %-7d 表示输出7位整数左对齐 
              %-10s 表示输出10个字符左对齐 
      
    • 实例
      #%d 显示十进制整数
      ~]#  echo "1.7 2.52" | awk '{printf ("%d\n",$2)}'
      2
      
      #%f 显示浮点数       
      ~]# echo "1.7 2.52" | awk '{printf ("%f\n",$1)}'
      1.700000
      
      #四舍五入输入整数
      ~]# echo "1.5" | awk '{printf ("%.f\n",$1)}'    
      2
      echo "1.4" | awk '{printf ("%.f\n",$1)}'    
      1
      
      #以3位长度、1位小数,"."占一位,浮点换行输出第2个域(四舍五入)
      ~]# echo "1.7 2.52" | awk '{printf ("%3.1f\n",$2)}'
      2.5
      
      #以6位长度,其中整数占2位,不足2位空格补足,“.”占一位,小数占3位,不足3位用0补足
      ~]# echo "1.7 2.52" | awk '{printf ("%6.3f\n",$2)}'
      2.520
      
      #指数形式的浮点数输出
      ~]# echo "1.7 2.52" | awk '{printf ("%e\n",$1)}'
      1.700000e+00
      
      #用0补充格式
      ~]# echo "123 1" | awk '{printf("%d\t%03d\n",$1,$2)}'
      123     001
      
  • BEGIN/END模式
    BEGIN{}: 仅在开始处理文件中的文本之前执行一次;
    END{}:仅在文本处理完成之后执行一次;
    
    • 实例
      #开头显示“The data of passwd”
      localhost ~]# awk 'BEGIN{print "The data of passwd"} {print}' /etc/passwd
      The data of passwd
      root:x:0:0:root:/root:/bin/bash
      bin:x:1:1:bin:/bin:/sbin/nologin
      daemon:x:2:2:daemon:/sbin:/sbin/nologin
      
      #显示第一行,并在开头和末尾显示“The data of passwd”
      localhost ~]# awk 'BEGIN{print "print /etc/passwd"} NR==1{print} END{print "print /etc/passwd"}' /etc/passwd
      print /etc/passwd
      root:x:0:0:root:/root:/bin/bash
      print /etc/passwd
      
  • 使用变量
    • 内建变量:字段和记录分隔符变量
      FS:input field seperator,输入字段分隔符,默认为空白字符
      OFS:output field seperator,输出字段分隔符, 默认空白字符;
      RS:input record seperator,输入时的换行符;
      ORS:output record seperator,输出时的换行符;
      FIELDWIDTHS:指定列
      
      • 实例
      • FS&OFS
        #自定义分输入隔符为“:”
        localhost ~]#awk 'BEGIN{FS=":"} NR<4{print $1,$2,$3}' /etc/passwd
        root x 0
        bin x 1
        daemon x 2
        
        #自定义分输入隔符为“:”,输出分隔符为“-”
        localhost ~]# awk 'BEGIN{FS=":" ;OFS="-"} NR<4{print $1,$2,$3}' /etc/passwd
        root-x-0
        bin-x-1
        daemon-x-2
        
      • RS&ORS
        #输入时以回车符为分隔符,空白行为换行符,
        localhost tmp]# cat data2
        Riley Mullen
        123 Main Street
        Chicago, IL 60601
        (312)555-1234
        
        Frank Williams
        456 Oak Street
        Indianapolis, IN 46201
        (317)555-9876
        
        Haley Snell
        4231 Elm Street
        Detroit, MI
        (313)555-4938
        localhost tmp]# awk 'BEGIN{FS="\n"; RS=""}{print $1 ,$4}' data2
        Riley Mullen (312)555-1234
        Frank Williams (317)555-9876
        Haley Snell (313)555-4938
        
      • FIELDWIDTHS
        #以特定列为分隔
        localhost tmp]# cat data1
        1005.3247596.37
        115-2.349194.00
        05810.1298100.1
        localhost tmp]# awk 'BEGIN{FIELDWIDTHS="3 5 2 5"} {print $1,$2,$3,$4}' data1
        100 5.324 75 96.37
        115 -2.34 91 94.00
        058 10.12 98 100.1
        
    • 自定义变量
      • 在脚本中给变量复制
        变量名可以是任意数目的字母、数字和下划线,但不能以数字开头
        
        • 实例
          localhost ~]#awk 'BEGIN{test="hello everyone";print test}'
          hello everyone
          
          localhost ~]# awk 'BEGIN{x=4;x=x*2+3;print x}'
          11
          
      • 在命令行上给变量复制
        localhost tmp]# cat data4
        data11 data12 data13
        data21 data22 data23
        data31 data32 data33
        
        localhost tmp]# cat script1
        BEGIN{print "The starting value is",n}{print $n}
        
        localhost tmp]# awk -v n=3 -f script1 data4
        The starting value is 3
        data13
        data23
        data33
        
  • 数组变量
    var[index] = element
    var:变量名
    index:索引值
    element:数据元素值
    
    • 遍历数组变量
      for (var in array)
      {
          statements
      }
      

      for语句在每次循环时将关联数组array下一个索引值赋给变量var,然后执行一遍statements

      • 实例
        localhost ~]# awk 'BEGIN{var["a"] =1;var["b"]=2;var["c"]=3;var["d"]=4;for (i in var) {print var[i]}}'
        1
        2
        3
        4
        
        #统计IP链接数
        localhost ~]# awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
        192.168.1.48 10
        
        #统计tcp链接状态和数量,IPV4
        localhost ~]# netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) { print i,state[i]}}'
        LISTEN 2
        ESTABLISHED 3
        
        #统计/etc/fstab文件中每个文件系统类型出现的次数
        localhost ~]# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab
        xfs 1
        
        #统计指定文件中每个单词出现的次数;
        localhost ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
        
  • 字符串匹配
    //          纯字符匹配   
    !//         纯字符不匹配  
     ~//        字段值匹配    
    !~//        字段值不匹配   
    ~/a1|a2/    字段值匹配a1或a2   
    
    • 实例
      #显示mysql相关信息
      localhost ~]# awk '/mysql/{print $0}' /etc/passwd 
      mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin
      
      #显示非mysql
      localhost ~]# awk '!/mysql/{print $0}' /etc/passwd 
      
      #显示mail和mysql
      localhost ~]# awk '/mail|mysql/{print $0}' /etc/passwd 
      mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
      mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin
      
      #显示$1匹配mail 
      localhost ~]# awk -F: '$1~/mail/{print $1}' /etc/passwd 
      mail
      
  • 操作符
    • 算数操作符
      x+y: 加
      x-y:减
      x*y:乘
      x/y:除
      x^y:次方
      x%y:余数
      
    • 赋值操作符
      = : x=y
      +=: x+=5    (x=x+5)
      -=: x-=5    (x=x-5)
      /=: x/=5    (x=x/5)
      %=: x%=5    (x=x%5)
      ^=: x^=5    (x=x^5)
      ++: x++     (x=x+1)
      --: x--     (x=x-1)
      
    • 比较操作符
      >
      >=
      <
      <=
      !=
      ==
      
    • 模式匹配符
      ~:是否匹配
      !~:是否不匹配
      
    • 逻辑操作符:
      &&
      ||
      !
      
    • 条件表达式
      selector?if-true-expression:if-false-expression
      
      实例:
       ~]# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
                 root:Sysadmin or SysUser
                  bin:Sysadmin or SysUser
               daemon:Sysadmin or SysUser
                  adm:Sysadmin or SysUser
                   lp:Sysadmin or SysUser
                 sync:Sysadmin or SysUser
      
  • 控制语句
    • if语句
      if(condition) {statments} 
      if(condition) {statments} else {statements}
      

      实例:

      #简单的if语句
      ~]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
      root
      centos
      test
      linux
      testuser
      
      #if-else语句
      ~]# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
      ~]#awk -F: '{if($3>=1000) printf "Common user: %s\n",$1; else printf "root or Sysuser: %s\n",$1}' /etc/passwd
      root or Sysuser: root
      root or Sysuser: bin
      root or Sysuser: daemon
      root or Sysuser: adm
      root or Sysuser: lp
      
      #在if中执行多条语句和if-else语句
      [root@localhost tmp]# cat data1
      10
      5
      13
      50
      34
      [root@localhost tmp]# awk '{if ($1>20) {x= $1*2; print $1,x}}' data1
      50 100
      34 68
      ~]# awk '{if($1>20) print $1*2;else print $1/2}' data1
      5
      2.5
      6.5
      100
      68
      
      #打印磁盘使用率超过10%的
       ~]#  df -h | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>=10) print $1}'
      /dev/mapper/cl-root
      /dev/sda1
      
    • while循环
      while(conditon) {statments}
      条件“真”,进入循环;条件“假”,退出循环
      

      实例:对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用

      ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg
      linux16 7
      /vmlinuz-3.10.0-514.el7.x86_64 30
      root=/dev/mapper/cl-root 24
      ro 2
      crashkernel=auto 16
      rd.lvm.lv=cl/root 17
      rd.lvm.lv=cl/swap 17
      rhgb 4
      quiet 5
      LANG=en_US.UTF-8 16
      linux16 7
      /vmlinuz-0-rescue-071d709683fd4359a4845645d1906b29 50
      root=/dev/mapper/cl-root 24
      ro 2
      crashkernel=auto 16
      rd.lvm.lv=cl/root 17
      rd.lvm.lv=cl/swap 17
      rhgb 4
      quiet 5
      
      ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /etc/grub2.cfg
      linux16 7
      /vmlinuz-3.10.0-514.el7.x86_64 30
      root=/dev/mapper/cl-root 24
      crashkernel=auto 16
      rd.lvm.lv=cl/root 17
      rd.lvm.lv=cl/swap 17
      LANG=en_US.UTF-8 16
      linux16 7
      /vmlinuz-0-rescue-071d709683fd4359a4845645d1906b29 50
      root=/dev/mapper/cl-root 24
      crashkernel=auto 16
      rd.lvm.lv=cl/root 17
      rd.lvm.lv=cl/swap 17
      
    • do-while循环
      至少执行一次循环体 
      
    • for循环
      for(expr1;expr2;expr3) {statements}
      

      实例

      ~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
      linux16 7
      /vmlinuz-3.10.0-514.el7.x86_64 30
      root=/dev/mapper/cl-root 24
      ro 2
      crashkernel=auto 16
      rd.lvm.lv=cl/root 17
      rd.lvm.lv=cl/swap 17
      rhgb 4
      quiet 5
      LANG=en_US.UTF-8 16
      linux16 7
      /vmlinuz-0-rescue-071d709683fd4359a4845645d1906b29 50
      root=/dev/mapper/cl-root 24
      ro 2
      crashkernel=auto 16
      rd.lvm.lv=cl/root 17
      rd.lvm.lv=cl/swap 17
      rhgb 4
      quiet 5
      
  • 内建函数
    • 数学函数
      atan2(x, y)     x/y的反正切,x和y以弧度为单位
      cos(x)          x的余弦,x以弧度为单位
      exp(x)          x的指数函数
      int(x)          x的整数部分,取靠近零一侧的值
      log(x)          x的自然对数
      rand( )         比0大比1小的随机浮点值
      sin(x)          x的正弦,x以弧度为单位
      sqrt(x)         x的平方根
      srand(x)        为计算随机数指定一个种子值
      
    • 字符串函数
      asort(s [,d])               将数组s按数据元素值排序。索引值会被替换成表示新的排序顺序的连续数字。另外,如果指定了d,则排序后的数组会存储在数组d中
      asorti(s [,d])              将数组s按索引值排序。生成的数组会将索引值作为数据元素值,用连续数字索引来表明排序顺序。另外如果指定了d,排序后的数组会存储在数组d中
      gensub(r, s, h [, t])       查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果h是一个以g或G开头的字符串,就用s替换掉匹配的文本。如果h是一个数字,它表示要替换掉第h处r匹配的地方
      gsub(r, s [,t])             查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果找到了,就全部替换成字符串s
      index(s, t)                 返回字符串t在字符串s中的索引值,如果没找到的话返回0
      length([s])                 返回字符串s的长度;如果没有指定的话,返回$0的长度
      match(s, r [,a])            返回字符串s中正则表达式r出现位置的索引。如果指定了数组a,它会存储s中匹配正则表达式的那部分
      split(s, a [,r])            将s用FS字符或正则表达式r(如果指定了的话)分开放到数组a中。返回字段的总数
      sprintf(format,variables)   用提供的format和variables返回一个类似于printf输出的字符串
      sub(r, s [,t])              在变量$0或目标字符串t中查找正则表达式r的匹配。如果找到了,就用字符串s替换掉第一处匹配
      substr(s, i [,n])           返回s中从索引值i开始的n个字符组成的子字符串。如果未提供n,则返回s剩下的部分
      tolower(s)                  将s中的所有字符转换成小写
      toupper(s)                  将s中的所有字符转换成大写
      
    • 时间函数
      mktime(datespec)            将一个按YYYY MM DD HH MM SS [DST]格式指定的日期转换成时间戳值①
      strftime(format[,timestamp])将当前时间的时间戳或timestamp(如果提供了的话)转化格式化日期(采用shell函数date()的格式)
      systime( )                  返回当前时间的时间戳

 

本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/101093

发表评论

登录后才能评论

This site uses Akismet to reduce spam. Learn how your comment data is processed.

联系我们

400-080-6560

在线咨询:点击这里给我发消息

邮件:1823388528@qq.com

工作时间:周一至周五,9:30-18:30,节假日同时也值班