awk

文本处理工具awk

1. 简介

  • 来由与做用
    awk是由Aho, Weinberger, Kernighan三位大牛开发的程序,用于报告生成器,格式化文本输出,可接收标准输入
  • 版本php

  1. New awk(nawk)
  2. GNU awk( gawk),centos使用的为gawk
  • 运行原理css

    1. 分割符、域和记录linux

    1. awk执行时,由分隔符分隔的字段(域)标记1,1,0为全部域,注意:和shell中变量$符含义不一样
    2. 文件读入内存空间的每一行称为记录,文本中的一行能够为多个记录
    3. 省略action,则默认执行 print $0 的操做
  • 工做原理nginx

    1. 执行BEGIN{action;… }语句块中的语句
    2. 从文件或标准输入(stdin)读取一个记录到内存空间,执行pattern{ action;… }语句块,匹配预约义的模式,若是不匹配就不处理,匹配后按照预先规定好的分隔符切割成若干字段,分割成功后,系统会对这些列分配一个域标识$1..$n,直到文件所有被读取完毕。
    3. 当读至输入流末尾时,执行END{action;…}语句块web

    1. BEGIN语句块在awk开始从输入流中读取行以前被执行,这是一个可选的语句块,好比变量初始化、打印输出表格的表头等语句一般能够写在BEGIN语句块中
    2. END语句块在awk从输入流中读取完全部的行以后即被执行,好比打印全部行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块
    3. pattern语句块中的通用命令是最重要的部分,也是可选的。若是没有提供pattern语句块,则默认执行{ print },即打印每个读取到的行,awk读取的每一行都会执行该语句块

    2. 基本用法

    • 格式:
      awk [options] var=value ‘program’ file…
    • 选项(options):正则表达式

    1. -v var=value: 自定义变量
    2. -f programfile: 读取文件中的程序
      awk [options] var=value -f programfile file…
    3. -F:指明输入时用到的字段分隔符,分隔符能够指定多个sql

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    示例:指定[;]为记录分隔符,下例为2个记录a:b@c:d与1:2@3 1:指定[:]为字段分割符 $echo "a:b@c:d;1:2@3"|awk -v RS=";" -F":" '{print $1,$3}' a d 1 2:指定[@:]为字段分割符 $echo "a:b@c:d;1:2@3"|awk -v RS=";" -F"[@:]" '{print $1,$3}' a c 两个分隔符都起做用,c为第3个字段 1 3 3:以扩展正则表达式方法表示也能够 $echo "a:b@c:d;1:2@3"|awk -v RS=";" -F"@|:" '{print $1,$3}'
  • program
    为awk本身的语法,一般是被单引号或双引号中,建议使用单引号,由于双引号在程序中会在字符串上用,避免混用shell

    1. 格式:
      1. BEGIN语句块、可以使用模式匹配的通用语句块、END语句块,共3部分组成
        ‘BEGIN{ action;… } pattern{ action;… } END{ action;… }’
      2. 经常使用格式:
        pattern{action statements;..}
    2. 释义pattern和action:
      1. pattern部分决定动做语句什么时候触发及触发事件
      2. action statements对数据进行处理,放在{ }内指明
        1. action格式: {print|printf item1, item2, …}
        2. 要点:
          1. 逗号分隔符
          2. 输出的各item能够字符串,也能够是数值;当前记录的字段、变量或awk的表达式
          3. 如省略item,至关于print $0
  • 示例
    例如:打印出/etc/passwd文件的第1和第3行express

  •  
     
     
     
     
    • 1
    awk -F: '{print $1,$3}' /etc/passwd

    3. awk变量

    变量:分为内置和自定义变量,只要对变量赋值,就要放在选项-v的后面apache

    3.1 内置变量

    • FS(field separator):输入字段分隔符,默认为空白字符,指定变量的好处在于,能够屡次调用

    1. 示例1:定义FS=’:’,在(程序)中调用变量

      $awk -v FS=':' '{print $1,FS,$3}’ /etc/passwd
      named:25
    2. 示例2:一次引用多个变量,中间须要使用逗号隔开

      $awk -v FS=: '{print $1FS,FS,FS$3}' /etc/passwd
      named: : :25
    3. 示例3:还能够引用shell中的变量,先声明fs=:,而后用awk调用

      $fs=:;awk -v FS="$fs" '{print $1FS$3}' /etc/passwd
      named:25
  • OFS(output field separator):指定输出字段分隔符,默认为空白字符

    1. 示例:以###做为字段分隔符

      $awk -F":" -v OFS=### '{print $1,$3,$2}' /etc/passwd
      named###25###x
  • RS(record separator):输入记录分隔符,指定输入时的换行符

    1. 示例:建立文本,以下awk.txt所示,[@,!,?]与[1,2,3,4]以及[A,B,C\naa,bb,cc],以[;]分隔开

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 建立实验文本 $cat awk.txt @,!,?;1,2,3,4;A,B,C aa,bb,cc 2. 指定输入字段分隔符为[,],输出字段分隔符为[==],输入记录分隔符为[;] $awk -v FS="," -v OFS="==" -v RS=";" '{print $3,$4}' awk.txt ?== <==第一个记录@,!,?没有第4个字段 3==4 <==第二个记录1,2,3,4,显示后两个 C <==第三个记录,保留原有格式换行,C\naa为第三个字段 aa==bb
  • ORS:输出记录分隔符,输出时用指定符号代替换行符

    1. 承上例,每条记录输出时默认为换行处理,能够经过ORS指定

     
     
     
     
     
    • 1
    • 2
    • 3
    $awk -v FS="," -v OFS="==" -v RS=";" -v ORS="***" '{print $3,$4}' awk.txt ?==***3==4***C <==记录输出时以指定的符号代替原回车换行 aa==bb***
  • NF:字段数量

  •  
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    $awk -F: '{print NF}' /etc/passwd 7 <==统计字段数量 $awk -F: '{print $(NF-6)}' /etc/passwd named <==显示第一列内容,至关于$1,要用括号括起来
  • NR:记录号

  •  
     
     
     
     
    • 1
    • 2
    $awk -F: '{print NR,$1}' /etc/passwd 45 named <==至关于多了个行号
  • FNR:各文件分别计数,记录号

  •  
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    $awk -F: '{print NR,$1}' /etc/passwd /etc/group 121 named <==一共有多少记录 处理多个文件时,使用NR会将记录号累计,不会按文件分开,这时须要使用FNR $awk -F: '{print FNR,$1}' /etc/passwd /etc/group 45 named <==/etc/passwd文件最后一个记录 76 named <==/etc/group文件最后一个记录
  • FILENAME:当前文件名
    承上例,若是以为显示不清楚,能够加上文件名

  •  
     
     
     
     
    • 1
    • 2
    $awk -F: '{print FNR,FILENAME,$1}' /etc/passwd /etc/group 76 /etc/group named
  • ARGC:命令行参数的个数

  •  
     
     
     
     
    • 1
    • 2
    $awk '{print ARGC}' /etc/passwd /etc/group 3 <==统计命令行参数的个数
  • ARGV:数组,保存的是命令行所给定的各参数
    上例为何是3个参数?使用ARGV查看各参数

  •  
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    $awk '{print ARGV[0] }' /etc/passwd /etc/group awk <==将awk算为了一个参数 $awk '{print ARGV[2] }' /etc/passwd /etc/group /etc/group <==第三个参数

    3.2 自定义变量(区分字符大小写)

    • 格式
      1. -v var=value 例如 -v NAME=USERNAME
      2. 直接在程序中定义变量{NAME=USERNAME;print…}
    • 示例

    1. 示例:使用格式1自定义

    $awk -F: -v USER=“username” -v UID=“userid” ‘{print USER":"$1,UID":"$3}’ /etc/passwd  /etc/group
    username:named userid:25 这样显示不是很清晰,还记得记录分隔符吗
    $awk -F: -v USER=“username” -v UID=“userid” -v ORS="\n------\n" ‘{print USER":"$1"\n"UID":"$3}’ /etc/passwd /etc/group

    username:screen
    userid:84

    username:named
    userid:25

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

  • 示例:使用格式2自定义

  •  
     
     
     
     
    • 1
    $awk -F: -v ORS="\n------\n" '{USER="username"; UID="userid"; print USER":"$1"\n"UID":"$3}' /etc/passwd /etc/group
  • 示例:将action放入文件,使用-f选项

  •  
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 将程序内容放入文件awk2.txt 中 $cat awk2.txt {USER="username"; UID="userid"; print USER":"$1"\n"UID":"$3} 2. 执行如下命令,写入文件的程序就不须要单引号了 $awk -F: -v ORS="\n------\n" -f awk2.txt /etc/passwd

    4. action中的printf命令

    • 格式
      printf “FORMAT”, item1, item2, …
    • 注意事项

    • 必须指定FORMAT
    • 不会自动换行,须要显式给出换行控制符,\n
    • FORMAT中须要分别为后面每一个item指定格式符
  • 格式符:与item对应

  • 符号 释义
    %c 显示字符的ASCII码
    %d, %i 显示十进制整数
    %c 显示字符的ASCII码
    %e, %E 显示科学计数法数值
    %g, %G 以科学计数法或浮点形式显示数值
    %s 显示字符串
    %u 无符号整数
    %% 显示%自身
    • 修饰符

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

  • 示例1: 取出/etc/passwd第1,3行,并在其前分别加Username和UID

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

    示例2:%s对应$1,表示文件第一行为字符串,在%与s中间能够添加参数[-]表示左对齐[20]表示第一列所占宽度,同理%-4d表示$2占4个字符宽度左对齐

     
     
     
     
     
    • 1
    • 2
    • 3
    $awk -F: '{printf"|%-20s %-4d|\n---------------------------\n",$1,$3 }' /etc/passwd |named 25 | ---------------------------

    示例3:在这里演示一下BEGIN的效果,添加表头,效果以下

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    $awk -F: 'BEGIN{print "|user |ID |\n----------------------------"}''{printf"|%-20s |%-4d|\n----------------------------\n",$1,$3 }' /etc/passwd |user |ID | <==头部,BEGIN所述内容 ---------------------------- |root |0 | <==文件内容,printf所述内容 ----------------------------

    示例4:小数处理示例

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1$echo "3.1415 1.15926" |awk '{printf "%2.2f;%1.4f",$1,$2}' 3.14;1.1593 %2.2f第一个2表示宽度,第二个2个小数点保留位数 %1.4f最后一位达到6时会进位 2$echo "3.1415 1.15925" |awk '{printf "%2.2f;%1.4f",$1,$2}' 3.14;1.1592 %1.4f最后一位值为5时不会进位 3$echo "3.1415 11.15925" |awk '{printf "%2.2f;%10.4f",$1,$2}' 3.14;***11.1593 <==这里为了显示效果,以***代替空格,共10个宽度 %10.4f宽度起做用了,说明宽度若是小于实际占用值,会以实际宽度为准

    5. 操做符

    5.1 算术操做符:

    操做符 定义
    +
    -
    *
    /
    % 取余
    ^
    -x 转换为负数
    +x 转换为数值

    5.2 赋值操做符:

    操做符 定义
    = 赋值
    += 将加的结果赋给变量
    -= 将减的结果赋给变量
    *= 将乘的结果赋给变量
    /= 将除的结果赋给变量
    %= 将取余的结果赋给变量
    ^= 将取幂的结果赋给变量
    ++ 变量加1
    变量减1

    • 示例:下面两语句有何不一样
      awk ‘BEGIN{i=0;print ++i,i}’
      awk ‘BEGIN{i=0;print i++,i}’
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    [root@hai7 ~]$awk 'BEGIN{i=10;print ++i,i}' 11 11 先递增,再将递增值打印 [root@hai7 ~]$awk 'BEGIN{i=10;print i++,i}' 10 11 先打印i值,再递增

    5.4 比较操做符:

    操做符 定义
    == 等于
    != 不等于
    > 大于
    >= 大于等于
    < 小于
    <= 小于等于

    5.5 模式匹配符

    操做符 定义
    ~ 左边是否和右边匹配
    !~ 是否不匹配

    • 示例
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    1:筛选文件/etc/passwd中包含root的行 [root@hai7 ~]$awk -F: '$0 ~ /root/{print NR$1}' /etc/passwd 1 root 10 operator 2:筛选文件/etc/passwd中以root开头的行 [root@hai7 ~]$awk -F: '$0 ~ "^root"{print NR,$1}' /etc/passwd 1 root 3:筛选文件/etc/passwd中不包含root的行 [root@hai7 ~]$awk -F: '$0 !~ /root/{print NR,$1}' /etc/passwd 2 bin 9 mail 11 games 4:筛选第三字段为0的行 [root@hai7 ~]$awk -F: '$3==0' /etc/passwd root:x:0:0:root:/root:/bin/bash

    5.6 逻辑操做符:与&&,或||,非!

    操做符 定义
    && 逻辑与
    逻辑非

    • 示例
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1:筛选第3个字段大于等于50而且小于等于60的行 [root@hai7 ~]$awk -F: '$3>=50 && $3<=60 {print NR,$1}' /etc/passwd 31 tss 2:筛选第3个字段等于0或大于等于1000的行 [root@hai7 ~]$awk -F: '$3==0 || $3>=1000 {print NR,$1}' /etc/passwd 1 root 29 nfsnobody 43 dong 3:筛选第3个字段小于等于1000之外的行 $awk -F: '!($3<=1000) {print NR,$1}' /etc/passwd 29 nfsnobody
    • 条件表达式(三目表达式):
      (selector1)?if-true(expression2):if-false(expression)
      先求表达式selector1的值,若是为真,则执行表达式2,并返回表达式2的结果;若是表达式1的值为假,则执行表达式3,并返回表达式3的结果。

    • 示例:
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    先定义条件第3字段大于等于1000,若是成立则打印type="user",不成立打印type="sys" [root@hai7 ~]$awk -F: '{$3>=1000?type="user":type="sys";printf"%+15s %s\n" ,$1,type}' /etc/passwd root sys nfsnobody user

    6 awk-PATTERN

    • PATTERN:根据pattern条件,过滤匹配的行,再作处理

    1. 若是未指定:空模式,匹配每一行
    2. /regular expression/:仅处理可以模式匹配到的行,须要用/ /括起来

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    例1:判断磁盘利用率,取出设备行 $df|awk -F " +|%" '/^\/dev\/sd/{print $1,$5}' /dev/sda2 11 /dev/sda3 1 /dev/sda1 16 例2:统计磁盘文件系统类型 $awk -F" +" '/^UUID/{print $3}' /etc/fstab|sort|uniq -c 2 swap 3 xfs
  • relational expression: 关系表达式,结果为“真”才会被处理

    • 真:结果为非0值,非空字符串
    • 假:结果为空字符串或0值
    • 示例

    1. 空格或者非0数值,返回值为非空,结果都为真,能够打印结果
      awk -F: '" "{print $1}' /etc/passwd
      awk -F: '1{print $1}' /etc/passwd
      awk ‘!0’ /etc/passwd
    2. 空值或者0,返回值为空,结果为假,不作处理
      awk -F: ' ""{print $1} ' /etc/passwd
      awk -F: '0{print $1}' /etc/passwd
      awk ‘!12345’ /etc/passwd 任何非0值取反都为空
    3. 下例分为两条命令

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    [root@hai7 ~]$awk -F: 'i=1;j=1{print i,j}' /etc/passwd named:x:25:25:Named:/var/named:/sbin/nologin 1 1 i=1;j=1{print i,j}是两条命令 i=1省略了{print ...}因此默认打印$0 seq 10 |awk ‘i=0’
  • 取偶数行或奇数行
    打印奇数行,由于i没有指定值因此为空,第一次执行时为空=!空,因此打印1,第二次执行时,非空=!非空值为0,因此不处理,以此类推,能够经过seq 10 | awk '{i=!i;print i}'查看返回结果
    • seq 10 |awk 'i=1'打印全部数字
    • seq 10 | awk 'i=!i'打印奇数行
    • seq 10 | awk '!(i=!i)'打印偶数行
    • seq 10 |awk -v i=1 'i=!i'打印偶数行
  • line ranges:行范围

    • 利用正则表达式写法取范围
      startline,endline:/pat1/,/pat2/ 不支持直接给出数字格式
      awk -F: ‘/^root\>/,/^nobody\>/{print $1}' /etc/passwd

    • 先要处理指定的行范围,能够利用NR记录编号来实现
      awk -F: '(NR>=10&&NR<=20){print NR,$1}' /etc/passwd

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

    • 示例

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    示例1: [root@hai7 ~]$awk -F : 'BEGIN {print "USER USERID"} {print $1":"$3} END{print "end file"}' /etc/passwd USER USERID <==BEGIN的内容 root:0 apache:48 named:25 end file <==END的内容 示例2: $awk -F: '{print "USER USERID";print $1":"$3} END{print "end file"}' /etc/passwd USER USERI <==不是开始处理的文本,会被循环打印 root:0 USER USERI bin:1

    7. awk action

    7.1awk控制语句if-else

    • 语法
      if(condition){statement;…}[else statement]
      if(condition1){statement1}else if(condition2){statement2}else{statement3}
    • 使用场景:对awk取得的整行或某个字段作条件判断
    • 示例:

    示例1:取出第3字段大于等于1000的行

     
     
     
     
     
    • 1
    • 2
    • 3
    awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd awk -F: '$3>=1000{print $1,$3}' /etc/passwd 效果相同,格式不一样控制语句是action里的要写在花括号内,判断语句是属于patter的要写在花括号外面

    示例2:取磁盘利用率高于5%的

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    $df|awk -F" +|%" '/^\/dev\/sd/{if($5>5){print $1,$5;print "it is full"}}' /dev/sda2 11 it is full /dev/sda1 16 it is full

    示例3:取访问日志中IP地址重复次数超过100的,放到防火墙中

     
     
     
     
     
    • 1
    • 2
    • 3
    [root@hai7 ~]$ab -c10 -n 100 http://172.20.50.201/ 实验准备屡次访问某地址 [root@hai7 ~]$cat /var/log/httpd/access_log|awk -F" " '{print $1}'|uniq -c|awk -F" " '{if($1>100){print $2}'|while read ip;do iptables -A INPUT -s $ip -j REJECT;done [root@hai7 ~]$iptables -F 清空防火墙

    示例3:shell类型使用bash的行

     
     
     
     
     
    • 1
    awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd

    示例4:第3字段大于等于1000的标记为Common user,不然标记为root or Sysuser

     
     
     
     
     
    • 1
    • 2
    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

    7.2 awk控制语句 while循环

    • 语法:
      while(condition){statement;…}
    • 条件“真”,进入循环;条件“假”,退出循环
    • 使用场景:
      对一行内的多个字段逐一相似处理时使用
      对数组中的各元素逐一处理时使用
    • 示例:

    示例1:用awk写1..100相加

     
     
     
     
     
    • 1
    • 2
    $awk 'BEGIN{sum=0;i=1;while(i<=100){sum+=i;i++};print sum}' 5050

    示例2:找出无论前面多少空格linux16开头的行,统计各字段字符串长度

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    [root@hai7 ~]awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i); i++}}' /etc/grub2.cfg 示例中length是系统函数,用来统计括号中字符串长 [root@hai7 ~]$awk 'BEGIN{print length("sdgdgasdfwergejut")}' 17

    示例3:统计字段字符串长度超过10的

     
     
     
     
     
    • 1
    awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=10) {print $i,length($i)}; i++}}' /etc/grub2.cfg

    示例4:判断随机数最大值与最小值

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1:生成以逗号为分隔符的随机数到文件f1 [root@hai7 ~]$(echo "$RANDOM" ;for((i=1;i<100;i++));do echo -n ",$RANDOM";done)>f1 2: 取出随机数最大值和最小值 [root@hai7 ~]$awk -F',' '{max=$1;min=$1;i=2;while(i<=NF){if($i>max){max=$i}else if($i<min){min=$i};i++;}}END{print "max="max,"min="min}' f1 max=32377 min=148 3:判断结果是否正确 [root@hai7 ~]tr ',' '\n' <f1.txt|shot -nr

    7.3 控制语句 do-while循环

    • 语法
      do {statement;…}while(condition)
    • 意义
      不管真假,至少执行一次循环体
    • 示例:

    示例1:1..100相加

     
     
     
     
     
    • 1
    $awk 'BEGIN{sum=0;i=1;do {sum+=i;i++}while(i<=100);print sum}

    示例2:统计linux16行,大于10个字符的字段

     
     
     
     
     
    • 1
    $awk '/^[[:space:]]*linux16/{i=1;do {if(length($i)>=10){print $i,length($i)}; i++}while(i<=NF)}' /etc/grub2.cfg

    7.4 awk控制语句 for循环

    • 语法
      for(expr1;expr2;expr3) {statement;…}
    • 常见用法:
      for(variable assignment;condition;iteration process){for-body}
    • 特殊用法:可以遍历数组中的元素
      - 语法:for(var in array) {for-body}
    • 示例:

    示例1:统计linux16行,各字段字符长度,

     
     
     
     
     
    • 1
    awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg

    示例2:从1+到100相加

     
     
     
     
     
    • 1
    awk 'BEGIN{sum=0;for(i=1;i<=100;i++)sum+=i;print sum}'

    7.5 awk控制语句 switch语句

    • 语法:
      swich定义的表达式,是否为case后的只或者正则表达式,若是是则执行statement1, 若是不匹配则继续判断第二个case后的值是否匹配,匹配则执行statement2,都不匹配则执行default后续。

    • 格式
      switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; …; default: statementn}

    7.6 awk控制语句 break、continue及next

    • break [n] 结束整个循环体

     
     
     
     
     
    • 1
    • 2
    • 3
    [root@hai7 /etc/selinux]$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==50)break;sum+=i} ;print sum}' 1225 循环到50,就不日后加了
  • continue [n]结束单次循环
  •  
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1:i%2==1意思为奇数循环,跳过奇数循环,得偶数总和 [root@hai7 /etc/selinux]$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==1)continue;sum+=i} ;print sum}' 2550 2:结束第50次循环,会继续进行后续循环 [root@hai7 /etc/selinux]$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==50)continue;sum+=i} ;print sum}' 5000
    • next:
      提早结束对本行处理而直接进入下一行处理(awk自身循环)
     
     
     
     
     
    • 1
    • 2
    打印 奇数行 awk -F: '{if($3%2!=0)next;print NR,$1,$3}' /etc/passwd

    8. 性能比较

    使用awk、shell、bc计算100000相加,参考所用时间,判断工做性能
    一、awk for循环

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    [root@hai7 /etc/selinux]$time awk 'BEGIN{sum=0;for(i=1;i<=100000;i++)sum+=i ;print sum}' 5000050000 real 0m0.011s user 0m0.010s sys 0m0.001s

    二、awk while循环

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    2. $time awk 'BEGIN{sum=0;i=1;while(i<=100){sum+=i;i++};print sum}' 5050 real 0m0.003s user 0m0.002s sys 0m0.001s

    三、shell for循环

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    $time for((sum=0,i=1;i<=100000;i++));do let sum+=i;done;echo $sum real 0m0.666s user 0m0.666s sys 0m0.000s

    四、shell while循环

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    $time ( sum=0;i=1;while [ $i -le 100000 ] ;do let sum+=i;let i++;done;echo $sum) 5000050000 real 0m1.064s user 0m0.992s sys 0m0.072s

    五、bc计算

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    $time seq -s + 100000|bc 5000050000 real 0m0.041s user 0m0.036s sys 0m0.007s

    9. awk数组

    9.1 awk支持关联数组

    arr[“key”]=value 键值对,每一个键后面对应着相应的值, 当按下相应的键时, 就会输出相应的结果

    • 格式
      array[index-expression]
    • index-expression:
      • 可以使用任意字符串;字符串要使用双引号括起来
      • 若是某数组元素事先不存在,在引用时,awk会自动建立此元素,并将其值初始化为“空串”
      • 若要遍历数组中的每一个元素,要使用for循环,格式为for(var in array) {for-body}
    • 示例

    •awk ‘!arr[0]++dupfile0]++′dupfile去掉重复行,例如文件内容为cat f2
    abc
    cvb
    abc
    当awk读入第一行时,arr的下标为abc,没有赋值为空,取反为非空,因此打印第一行,arr[abc]=1
    读入第二行是,arr的下标为cbv,没有赋值为空,取反为非空,因此打印
    读入第三行时,arr的下标为abc,值为1,取反为空,因此不打印 arr[abc]=2

    去掉重复行还可使用sort -u f2
    •awk ‘{!arr[0]++;print0]++;print0, arr[$0]}’ dupfile

    分别定义数组weekdays的键值对为[“mon”]=”Monday”,[“tue”]=”Tuesday”,经过for来遍历

     
     
     
     
     
    • 1
    awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'

    统计tcp状态,NF表明最后一个字段,i表示值,state[i]表示累计结果

     
     
     
     
     
    • 1
    netstat -tan | awk '/^tcp/{state[$NF]++}END{for(i in state) { print i,state[i]}}'

    统计IP访问次数,f1为导出的IP访问日志格式为,默认以空格为分隔符
    172.20.7.53 - - [10/Sep/2018:10:18:53 +0800] “GET / HTTP/1.0” 403 4961 “-” “ApacheBench/2.3”

     
     
     
     
     
    • 1
    awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' f1|sort -rn

    分别统计男生女生的平

     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    [root@hai7 /data]$cat f2 name grade boyorgirls A 76 G B 98 M C 66 M D 95 G E 86 G F 79 M [root@hai7 /data]$awk '!/^name/{if($3=="M"){score_m+=$2;number_m++}else{score_g+=$2;number_g++}}END{print "avg_m="score_m/number_m"","avg_g="score_g/number_g}' f2 avg_m=81 avg_g=85.6667

    方法二

     
     
     
     
     
    • 1
    • 2
    • 3
    [root@hai7 /data]$awk 'NR!=1{score[$3]+=$2;num[$3]++}END{for(sex in num){print sex":avg="score[sex]/num[sex]}}' f2 G:avg=85.6667 M:avg=81

    9.2 自定义函数

    • 格式:
      function name ( parameter, parameter, … ) {
      statements
      return expression
      }
    • 示例:
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    cat fun.awk function max(v1,v2) { v1>v2?var=v1:var=v2 return var } BEGIN{a=3;b=2;print max(a,b)} awk –f fun.awk 3

    9.3 awk中调用shell命令

    空格是awk中的字符串链接符,若是system中须要使用awk中的变量可使用空格分隔,或者说除了awk的变量外其余一概用”“引用起来。

    • 格式 system(“$var”)
    • 示例
      awk BEGIN'{system("hostname") }'
      awk 'BEGIN{score=100; system("echo your score is " score) }'

    9.4 awk脚本

    将awk程序写成脚本,直接调用或执行

    • 示例
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    1:将pattern{action statements;..}写到文本中 [root@hai7 /data]$cat f3 {if($3>=1000)print $1,$3} 2:调用文原本筛选文件 $awk -F: -f f3 /etc/passwd nfsnobody 65534 v9 1000 3:创建awk执行脚本 $cat f3 #!/bin/awk -f <==脚本解释器与shell不一样 #this is a awk script {if($3>=1000)print $1,$3} <==pattern{action statements;..} 4:加执行权限 chmod +x f3 5:调用脚原本过滤文本 ./f3 –F: /etc/passwd

    9.4.1 向awk脚本传递参数

    • 格式
      awkfile var=value var2=value2… Inputfile
    • 注意事项
      • 在BEGIN过程当中不可用。直到首行输入完成之后,变量才可用。
      • 能够经过-v 参数,让awk在执行BEGIN以前获得变量的值。命令行中每个指定的变量都须要一个-v参数
    • 示例
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1:编辑awk脚本 cat test.awk #!/bin/awk –f {if($3 >=min && $3<=max)print $1,$3} 2:加执行权限 chmod +x test.awk 3:执行脚本,向脚本传递变量以下,也可使用-v min=100,每一个变量前都要加-v ./test.awk -F: min=100 max=200 /etc/passwd

    10. awk数值处理

    • rand():
      返回0和1之间一个随机数,须要配合srand实现,srand是用来生成随机数的种子
      awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }'
    • int 取整数
      例:生成随机1-1之间的小数awk 'BEGIN{srand();print rand()}'
      例:生成0-100之间的数awk 'BEGIN{srand();print int(rand()*100)}'

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

    • sub(r,s,[t])
      对t字符串进行搜索r(支持正则表达式)表示的模式匹配的内容,并将第一个匹配的内容替换为s
      [root@hai7 /data]$echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)'
      2008-08:08 08:08:08
    • gsub(r,s,[t])
      对t字符串进行搜索r表示的模式匹配的内容,并所有替换为s所表示的内容
      [root@hai7 /data]$echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$0)'
      2008-08-08 08-08-08
    • split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,…
     
     
     
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    用:作分隔符将2008:08:08 08:009:09分割为5段,分别存放在下标为1str[1]=2008str[2]=08... echo "2008:08:08 08:009:09"|awk '{split($0,str,":")}END{for(i in str)print i,str[i]}' 4 009 5 09 1 2008 2 08 3 08 08
    <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-7f770a53f2.css" rel="stylesheet">
                </div>
    相关文章
    相关标签/搜索
    本站公众号
       欢迎关注本站公众号,获取更多信息