美文网首页
awk的介绍和使用

awk的介绍和使用

作者: 一桥长书 | 来源:发表于2017-09-10 18:33 被阅读0次

    1 awk的介绍

    awk: Aho,Weinberger,Kernighan,报告生成器.格式化输出
    grep: 文本过滤 egrep pattern
    sed: 行编辑器 模式空间 保持空间
    
    基本用法
      gawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...
      gawk [ POSIX or GNU style options ] [ -- ] program-text file ...
      awk 程序通常使用:BEGIN语句块,能使用模式空间匹配的通用块,END语句块,共三部分组成
      program 通常使用单引号
      基本格式:awk [options] 'program' file…
      program:pattern{action statements;..}
      pattern 和action: :
        pattern 部分决定动作语句何时触发及触发事件
      BEGIN,END
        action statements 对数据进行处理,放在{} 内指明
        print, printf
      分割符、域和记录
        awk 执行时, 由 分隔符分隔的字段(域)标记$1,$2..$n称 称为域标识。$0 为所有域,注意:和shell 中变量$ 符含义不同
        文件的每一行称为记录
        省略action行 ,则默认执行 print $0 的 的 操作  
    
    print格式: print item1,item2 ...
    要点:
      1 逗号分隔
      2 输出的各item可以字符串,也可以是数值,当前记录的字段,变量或awk的表达式
      3 如果省略item 相当于print $0
    示例:
      1 awk '{print "hello"}'
      [root@test5(172.18.254.5) ~]#awk '{print "hello,world,awk" }'
      a
      hello,world,awk
      b
      hello,world,awk
      2  awk -F: '{print $0}' /etc/passwd
      [root@test5(172.18.254.5) ~]#awk -F: -v ORS=' ' '{print $1}' /etc/passwd
      root bin daemon adm lp sync shutdown halt mail uucp operator games gopher ftp nobody dbus vcsa abrt haldaemon ntp sasl
    auth postfix sshd tcpdump
      # 指明输出使用的记录分隔符
    

    2 awk 的变量 需要使用 -v 指定

    FS: 输入字段分隔符,默认为空白字符
    OFS: 输出字段分隔符,默认为空白字符
    RS: 输入记录分隔符,指定输入时的换行符,原换行符仍有效
    ORS: 输出记录分隔符,输出时用指定符号代替换行符
    NF: 字段数量
    NR: 行号,如果是多个文件,将一起计数
    FNR: 行号,如果是多个文件,将分别计数
    FILENAME: 当前参数文件名
    ARGV: 命令行参数的个数
    ARGV:数组,保存的是命令行所指定的各参数
      [root@test5(172.18.254.5) ~]#awk 'BEGIN{print   ARGV[0],ARGV[1],ARGV[2]}' /etc/passwd /etc/issue
      awk /etc/passwd /etc/issue
    # 用户自定义的变量
      awk –F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd
    
    printf命令 当使用printf的时候 print的变量有时候不起作用
    格式化输出: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
      +: 显示数值的正负符号 %+d
    
    将数字对应的ascii打印出来
      [root@test5(172.18.254.5) ~]#cat test.txt
      88 89 90
      [root@test5(172.18.254.5) ~]#awk '{i=1;while(i<=NF){printf "%c\n",$i;i++}}' test.txt 
      X
      Y
      Z
    将ascii对应的数字打印出来
      [root@test5(172.18.254.5) ~]#for i in {a..z};do printf "%d " "'$i";done
      97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 
    获取磁盘利用率
      df -P | awk -F"[% ]"  '/\/dev/&& $(NF-2) >= 10{print $1,$(NF-2)}'
    
    awk的一些定义
      awk 'BEGIN{i=0;print i++,i}'  1  1  i=i++ 
      awk 'BEGIN{i=0;print ++i,i}'  0  1  i=++i
    awk '{i=1;sum=0;while(i<=NF){sum+=$i;i++};print sum,i}' /file.txt 
     # 可以将 每行计算一个数字
    awk '{i=1;while(i<=NF){sum+=$i;i++};print sum,i}' /file.txt
    # 可以将 每行中的数加在一起   统计出来一个数字
    
    pattern 类似 sed 的定界符
    1 empty:空模式 匹配任一行
    2 /regular expression/:仅处理被pattern匹配到的行
    3 relational expression :关系表达式 结果 有真 有假 结果为真 才会被处理 假 过滤
      真 结果为非零 非空串;
      awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd
      awk -F: '$NF="/bin/bash"{print $1,$NF}' /etc/passwd
    4 line range 行范围
      tartline endline  /pat1/,/pat2/
      awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
    5 BEGIN/END 模式
      BEGIN():仅在开始处理文件中的文本之前执行一次  在未执行pattern中执行之前,执行END() 仅在文本处理完成之后执行一次
      awk -F: 'BEGIN{print "  USERNAME          uid   \n"}{printf "%-20s%3s\n",$1,$3}END{print "***************************\n          end"}' /etc/passwd
    

    3 控制语句

    if (condition) {statements}
    if (condition) {statements} else {statements}
    do {statements} while(condition)
    for (expr;expr2;expr3){statements}
    break
    continue
    delete array[index]
    delete array
    exit
    { statements }
    1 if-else
      语法 if(condition) statement [else statement]
        awk -F: '{if($NF~/bash$/) print $1,$NF}' /etc/passwd
        awk -F: '{if($3>1000) {printf "common user:%s\n",$1} else {printf "root or sysuser:%s\n",$1}}' /etc/passwd
        awk '{if(NF>7) print $0}' /etc/fstab
    df -hP | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>30) print $1}'
        使用场景:对awk取得的整行或某个字段做条件判断
    2  while
      语法 while (condition) statement
        条件为真 进入循环 条件为假 退出循环
        使用场景 对一行内的多个字段逐一做类似处理时使用,对数组中的各元素逐一处理使用
        awk '/^[[:space:]]+linux16/{i=1;while(i<NF){print $i,length($i);i++}}' /etc/grub2.cfg
        awk '/^[[:space:]]+linux16/{i=1;while(i<NF){if(length($i)>=7) print $i,length($i);i++}}' /etc/grub2.cfg 
    3 do..while
       语法 do statement while(condition)
        意义 至少运行一次
    4 for 循环
      语法 for(expr1;expr2;expr3) statement
        特殊用法
          能够遍历数组中的元素
          语法 for(var in array){for body}
    5 switch 语句
      语法:switch(expression) {case value or /pat/: statement;case value2 or /pat2/: statement;...default:statement}
    6 break和continue
      break [n] 退出几层循环
      continue 退出当前循环
    7 next 控制awk 的内生循环
      提前结束对本行的处理而直接进入下一行
        awk -F: '{if($3%2!=0) next;print $1,$3}' /etc/passwd
    

    4 数组

    关联数组 array[index-expression]
      index-expression 
        1 可使用任意字符串 字符串要是用双引号
        2 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其初始化为空串要判断数组中是否存在某元素,要是用index in array 格式进行
      去除重复的行
        awk -F":" '!a[$7]++' /etc/passwd
      显示行重复的次数
        awk -F":" '{!a[$0]++;print $0,a[$0]}' test.txt          
      若要遍历数组中的每一个元素,要是用for 循环
        for(var in array) statement
        awk 'BEGIN{weekends["mon"]="Monday";weekends["tue"]="Tuesday";for(i in weekends){print weekends[i]}}'
        注意 var 会遍历array 的每一个索引
        netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state){print i,state[i]}}'
        netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state){print i,state[i]}}'
    练习
        统计/etc/fstab 文件中每个单词出现的次数
    awk '{i=1;while(i<=NF){danci[$i]++;i++}}END{for(i in danci){print i,danci[i]}}' /etc/fstab
        统计/etc/fstab文件中 文件系统的类型及个数
    awk '/^\/dev|^UUID/{type[$3]++}END{for(i in type){print i,type[i]}}' /etc/fstab
    

    5 内置函数

    数值处理
      rand();返回0和1之间的随机数 只有第一次使用时随机的,(不做特殊处理)以后都会相同的
      需要生成一个种子 srand()
        awk 'BEGIN{srand();for(i=1;i<=10;i++)printf "%d ",rand()*100}'
        awk 'BEGIN{srand();print rand()}'
        awk 'BEGIN{srand();printf "%d",rand()*100 }'
        awk 'BEGIN{srand();print int(rand()*100) }'
    字符串处理
      length([s]) 返回字符串长度
      sub(r,s[t])以r表示的模式来查找t所代表的字符串中的匹配的内容,并将其第一次出现替换为s所代表的内容
        echo "2008:08:08 08:08:08" |awk 'sub(/:/,"-",$1)'
        2008-08:08
      gsub(r,s[t])以r表示的模式来查找t所代表的字符串中的匹配的内容,并  将所有出现均替换为s所代表的内容
        echo "2008:08:08 08:08:08" |awk 'gsub(/:/,"-",$1)'
        2008-08:08
      split(s,a[,r]):以r为分隔符切割s字符,并将切割后的结果保存至a所表示的数组当中下标从1开始
        netstat -tan | awk '/^tcp\>/{split($5,ip,":");print ip[1]}'
        netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'
    
    练习
    1 、统计/etc/fstab 文件中每个文件系统类型出现的次数
      awk '!/^#/&&!/^$/{type[$3]++}END{for(i in type){print i,type[i]}}' /etc/fstab
      awk '/^[^#]/{type[$3]++}END{for(i in type){print i,type[i]}}' /etc/fstab
    2 、统计/etc/fstab 文件中每个单词出现的次数
      awk '{i=1;while(i<=NF){danci[$i]++;i++}}END{for(i in danci){print i,danci[i]}}' /etc/fstab
    3 、提取出字符串Yd$C@M05MB%9&Bdh7dq+YVixp3vpw中 中的所有数字
      echo 'Yd$C@M05MB%9&Bdh7dq+YVixp3vpw' | awk -v FS="[^0-9]+"    '{i=1;while(i<=NF){{if($i ~ "[0-9]+")print $i};i++}}'
    4 、解决DOS 攻击生产案例:根据web 日志或者或者网络连接数,监控当某个IP 并发连接数或者短时内PV 达到100 ,即调用防火墙命令封掉对应的IP ,监控频率每隔5 分钟。防火墙命令为:iptables -A INPUT -s IP -j REJECT
    #!/bash
    declare -a dos
    while :;do
    dos=(`awk '{ip[$1]++}END{for(i in ip){if(ip[i]>100)print i}}' test.txt`)
        for i in ${dos[@]};do
            iptables -A INPUT -s $i -j REJECT
        done
    sleep 300
    done
    

    相关文章

      网友评论

          本文标题:awk的介绍和使用

          本文链接:https://www.haomeiwen.com/subject/rfltsxtx.html