zoukankan      html  css  js  c++  java
  • awk

     

    基础理论

    awk脚本是由模式和操作(动作)组成的

     

    模式

     

    模式可以是以下任意一个:

     1. /正则表达式/:使用通配符的扩展集。

     2.关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试。

     3. 模式匹配表达式:用运算符~(匹配)和~!(不匹配)。

     4.BEGIN语句块、pattern语句块、END语句块:

      

    动作:

     1.变量或数组赋值

     2.输出命令

     3.内置函数

     4.控制流语句

     

     

    awk基本结构

     

    一个awk脚本通常由:

    1. BEGIN语句块

    2.能够使用模式匹配的通用语句块。

    3. END语句块  3部分组成。

     

    格式如下:

    awk 'BEGIN{BEGIN部分的执行内容}{通用语句部分}END{结束后执行的内容}' 文件名

     

    解释:

    每一部分(除了BENGIN、END关键字外)都需要用{}扩起来。来区分这3个不同的部分。

     

    例子:

    awk 'BEGIN{print "---"}{print "china"}END{print "---"}' /etc/fstab

    执行结果如下:

    ---

    china

    china

    china

    china

    ---

     

    解释:

    1、 BEGIN{print "---"}为第一部分,BENGIN标识了后边括号中的内容为begin部分

    2、 {print "china"}为第二部分,通用语句块部分

    3、 END{print "---"}为第三部分,END标识了后边大括号中的内容为END部分的内容

     

    结束后要执行的语句块。

      

    这三个部分是可选的。任意一个部分都可以不出现在脚本中,脚本通常是被单引号双引号中.

     

    例子1

     只出现BEGIN部分

     [root@centos-1 ~]# awk 'BEGIN{print "---"}'

     --

     需要注意:

     只出现BEGIN部分,后边不需要跟文件名

     

    例子2

    只出现通用语句块部分

    [root@centos-1 ~]# awk '{print "china"}' /etc/fstab

    china

    china

    china

    china

    china

    china

    需要注意:

    只出现通用语句块部分,后边必须跟文件名。没有文件名不能正常处理

     

    例子3

    只出现END语句块部分

    [root@centos-1 ~]# awk 'END{print "---"}' /etc/fstab

    ---

    需要注意:

    只出现END语句块部分,后边必须跟文件名。没有文件名不能正常处理

     

    awk工作流原理

    第一步:执行BEGIN{}语句块中的语句;

     第二步:从文件或标准输入(stdin)读取一行,然后执行{通用语句块}语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。

     第三步:当读至输入流末尾时,执行END{}语句块。

      

    BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。

     

    END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。

     

    pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。

    常看awk版本

    [root@localhost pangbing]# awk -W version

    GNU Awk 3.1.7

    Copyright (C) 1989, 1991-2009 Free Software Foundation.

     


    2.域和记录
        

    域可以理解为”列”
    在默认情况下,awk把文件按照空格分成不用的域(也就是列),

     

    域的标记为$1 $2 $3.....。这种方法称为域标识。

     

     $0表示所有域。例子:awk '{print $0}' 文件名

     

     我们也可以通过-F选项来指定分割符,根据这个分割符把文件分成不同的域

        
    例子:awk '{print $0}' 文件名 > 文件名 | tee 文件名

    管道前边的结果会直接输出到文件,不会输出到屏幕上。tee命令就是能同时让结果输出到屏幕上。

       打印不同的域,中间用逗号隔开

         例子:'{print$1,$3,$7}'


    3.awk 匹配正则表达式
        
         元字符:
              这里是 a w k中正则表达式匹配操作中经常用到的字符:

              ^ $ . [] [^] | () * + ?
         条件操作符

         表9 - 2给出a w k条件操作符,后面将给出其用法。
        
         表9-2 awk条件操作符
         操 作 符     描 述          操 作 符      描 述

         <            小于              >=           大于等于

         <=           小于等于          ~           匹配正则表达式

         ==           等于            !~          不匹配正则表达式

         !=            不等于

    <1>  匹配
         为使某一域号匹配正则表达式,使用符号‘~’后紧跟正则表达式
        
         例子:

    awk  /root/ /etc/passwd 这个是简单的写法 ;passwd文件中只要含有root的行就打印出来

    root:x:0:0:root:/root:/bin/bash

    operator:x:11:0:operator:/root:/sbin/nologin

        

    awk -F:  '$1~/root/' /etc/passwd 意思是以:

    为分隔符号,打印第一段(区域)匹配含有root的行

    root:x:0:0:root:/root:/bin/bash

     

    awk -F: '$3~/0/' /etc/passwd 意思是以:为分隔符号,打印第三段(区域)匹配含有0的行

     

    awk -F: '$3=="0"' /etc/passwd 意思是以:为分隔符号,打印第三段(区域)匹配是0的行(这时精确匹配)

    awk '/^ /' 文件名      匹配以空格开头的行

    awk '/^ | ^#/' httpd.conf 匹配空格开头的或者是^#开头的

    awk '!(/表达式1/&& /表达式2/)' /etc/passwd

    表示取反

     

     

    <2>.  精确匹配

    为精确匹配 48,使用等号 ==并用单引号括起条件。例如 $3==“48” ,这样确保只有 4 8序号得以匹配,其余则不行。

    awk -F: '$3~/0/' /etc/passwd 意思是以:为分隔符号,打印第三段(区域)匹配含有0的行

        

    root:x:0:0:root:/root:/bin/bash

    uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

    avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin

         pangbing:x:500:500:pangbing:/home/pangbing:/bin/bash

        

    awk -F: '$3=="0"' /etc/passwd 意思是以:为分隔符号,打印第三段(区域)匹配只是0的行(这是精确匹配)

                                                              ################
         root:x:0:0:root:/root:/bin/bash    

    <3> 不匹配
         awk -F: '$3!="0"' /etc/passwd
         awk -F: '$3!~/0/' /etc/passwd
    <4>比较

         awk -F: '$3>=$4'  /etc/passwd

     

    4.计算

         

         [root@localhost pangbing]# cat 1

              1  11

              2  12

              3  14

              4  22

        

         <1>求和

        格式: awk '{变量名+=第几列}END{print 变量名}' 文件名

         [root@localhost pangbing]#

          awk  '{sum+=$1}END{print sum}' 1

              10

         [root@localhost pangbing]#

          awk '{sum+=$2}END{print sum}' 1

              59

        

         <2>求平均值

         格式:awk '{变量名+=第几列}END{print 变量名/NR}' 文件名

        

         [root@localhost pangbing]# awk    '{a+=$2}END{print a/NR}' 1

              14.75

     

    5.多条件同时匹配

         [root@localhost pangbing]# cat 1

              1  11 

              1  12 asd fff

              1  13 2

        

         同时匹配多个条件

         格式:awk '条件1 && 条件2 && 条件...' 文件名

         [root@localhost pangbing]#

    awk '$1~/1/ && $2~/12/' 1     

    awk '$1~"1" && $2~"12"' 1    //也可以用""代替

              1  12 asd fff

        

         <1>前提是用 匹配时可以用双引号替换//

              

         <2>/表达式/单独出现时,不要用双引号替换,结果会有误。

     

    时间段匹配

     

    [root@centos-1 ~]# cat c
    10:01
    10:02
    10:03
    10:05
    10:06
    10:07
    12:01
    11:01

     

    [root@centos-1 ~]# awk '$1>="10:05" && $1<="11:10"' c
    10:05
    10:06
    10:07
    11:01

    awk的时间匹配是不受时间顺序的影响

     

    [root@centos-1 ~]# awk '/10:05/,/11:10/' c
    10:05
    10:06
    10:07
    12:01
    11:01

    而这种匹配是受数值顺序的影响的,这里需要特别注意

     

                                            

    6.awk中的for循环

              [root@localhost pangbing]# cat b

                     pppppp

        

         

         

         例子:[root@localhost pangbing]# awk '{for (i=1;i<=10;i++) print i}' b

                 1

                               2

                               3

                               4

     

        

         其中

         for(i=1;i<=10;i++)循环的意思是:定义了一个取值列表

         for (变量=开始;停止循环的条件;步进长度)

         停止循环的条件:是指满足条件就循环,不满足就停止循环。

         误区我这个循环理错了:

              i做一次赋值运算,然后用i<=10这个条件判断i的值是不是小于10,然后做i的值做+1运算,然后i在从新赋值等于1,判断,运算。然后i在从新赋值等于1,判断,运算。我是这样错误理解这个循环的。这样i不是永远都 等于2了。

         正确理解:这里边真正的循环体是i=1

                   i<=10i++是给i=1循环时候添加的附加条件

                   i++定义了 i 循环时候的运算方式。是说你每次循环都加1

                   i<=10 :那么加到什么时候为止呢,i不在小于等于10的时候就停止循环。

        

         循环过程:i=1 判断是否满足条件,满足就1+1

                  这时i=2了。还满足条件  2+1

                  这时i=3.还满足条件  3+1

                  一直循环到不满足条件为止。

        <2>另一种for的写法

              这种写法和shell一样

              fori in 取值列表)

    4.  awk内置变量

         a w k有许多内置变量用来设置环境信息。这些变量可以被改变。表 9 - 3显示了最常使用的
         一些变量,并给出其基本含义
         A R G C 命令行参数个数
         A R G V 命令行参数排列
         E N V I R O N 支持队列中系统环境变量的使用
         FILENAME  a w k浏览的文件名
         F N R 浏览文件的记录数
         F S 设置输入域分隔符,等价于命令行 - F选项
         N F 浏览记录的域个数$NF表示最后一段。)
         N R 已读的记录数

         O F S 输出域分隔符
         O R S 输出记录分隔符
         R S 控制记录分隔符

     

    5.ifconfig eth0 | awk  -F[" ":]+ '/inet addr/ {print $4}'

    这是快速过滤出IP地址的方法

     

     

    echo 1234567890|awk -F "^C'{print $5}'

    5

     

    awk '{print $1,$NF,$(NF-1),$RS,$(NR-1),$(NR+1)}'

      

    统计ip次数

    awk '{print $1}' a.log |sort|uniq -c|sort -nr

    优化后

    awk '{a[$1]++}END{for (i in a)print a[i],i}'|sort -nr

     

    *

    a[$i]++

    创建一个哈希数组,数组的key是每一列的内容a1、b1、a1、c1......,数组的value是每一列出现的次数

     

    awk 哈希数组

     

    awk  printf 制表符

     

    过滤ip地址

    grep -o '([0-9]{1,3}.){3}[0-9]{1,3}' urfile

     

  • 相关阅读:
    不用循如何计算数组累加和
    mysql通过binlog恢复删除数据
    windows下打开binlog
    mysql的binlog
    枚举实现线程池单例
    AtomicInteger的CAS算法浅析
    不用循环如何计算1累加到100
    MongoDB查询报错:class com.mongodb.MongoSecurityException: Exception authenticating MongoCredential
    Senparc.Weixin微信开发(3) 自定义菜单与获取用户组
    Senparc.Weixin微信开发(2) 消息机制和上下文(Session)
  • 原文地址:https://www.cnblogs.com/pangbing/p/6535652.html
Copyright © 2011-2022 走看看