zoukankan      html  css  js  c++  java
  • AWK简介

    AWK简介

    AWK是文本处理三剑客的重要工具之一:

    文本处理三工具分别是:grep, sed, awk,具有如下特点:

    grep, egrep, fgrep:文本过滤工具依据pattern
    sed:行编辑器(模式空间,保持空间)
    awk:报告生成器,格式化文本输出

    AWK基本用法 

    基本格式:awk [options] 'program' file…

    • program:pattern{action statements;..}
    • pattern和action:
      • pattern部分决定动作语句何时触发及触发事件:BEGIN,END
      • action statements对数据进行处理,放在{}内指明:print, print

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

    下面对每一项做详细的说明

    1、print

    print item1, item2 ......
    要点:
    (1) 逗号分隔符
    (2) 输出的各item可以字符串,也可以是数值:当前记录的字段、变量或awk的表达式
    (3) 如省略item,相当于pring $0

    2、变量

    2.1 内建变量

    FS: input field seperator,默认为空白字符
    OFS:output field seperator,默认为空白字符
    RS: record(一行即一个record) input record seperator, 输入时的换行符
    ORS:output record seperator,输出时的换行符号
    awk -v RS=' ' '{print}' /etc/passwd 只定义了输入的换行符,输出额外默认的换行符依然作为换行符显示

    NF: number of fiels,每一行的字段数量(引用awk的内部变量不用$,而awk定义的$1,$2)

     {print NF} VS {print $NF}

    awk '{print NF}' /etc/fstab

    awk '{print $NF}' /etc/fstab 加$等于打印最后一个字段

    NR: number of record文件的行数(多个文件统一计数)
    FNR: 各文件分别计数,
    FILENAME:当前文件名:
    ARGC:命令行参数的个数
             awk 'BEGIN{print ARGC}' /etc/fstab /etc/issue
    ARGV:数组,保存的是命令行
             awk '{print ARGV[2]}' /etc/fstab /etc/issue

     2.2自定义变量

    (1) -v var=value
    变量名区分大小写
    awk -v test='hello gawk' '{print test}' /etc/issue(/etc/issue文件的作用是显示多少次)
    (
    2) 在progrm中直接定义
    awk 'BEGIN{test="hello gawk"; print test}' 直接在program中以变量赋值语句

     3、printf命令

    格式化输出:printf FORMAT, item1, item2 ......
    (1) FORMAT必须给出
    (2) 不会自动换行,需要显式给出换行控制符号
    (3) FORMAT中需要分别为后面的每个item指定一个格式化符号

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

    awk -F: '{printf "Username:%s ",$1}' /etc/passwd
    awk -F: '{printf "Username:%s, UID:%d ",$1,$3}' /etc/passwd

    修饰符:
    #[.#]:第一个数字控制显示的宽度;第二个#表示显示的精度
          awk -F: '{printf "Username:%15s, UID:%d ",$1,$3}' /etc/passwd (默认右对齐)
    -:左对齐
        awk -F: '{printf "Username:%-15s, UID:%d ",$1,$3}' /etc/passwd
    +:显示数值的符号

    4、操作符

    算术操作符:
    x+y,x-y,x*y,x^y,x%y
    -x:
    +x:转换为娄值
    字符串操作符:没有符号的操作符,字符串连接

    赋值操作符:
    =,+=,-=,*=,/=,%=,^=
    ++,--
    比较操作符:
    >, >=,<, <=, !=,==
    模式匹配符:
    ~:是否匹配
    !~:是否不匹配

    逻辑操作符:
    && 与
    || 或
    ! 非
    函数调用:
    function_name(argu1,argu2,......)

    条件表达式:
    selector?if-true-expression:if-false-expression
    awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmi";printf "%15s==%s ",$1,usertype}' /etc/passwd

    5、 PATTERN(类似sed中的地址定界)

    (1) empty: 空模式,匹配每一行
    (2) /regular expression/: 仅处理此能够被此处的模式匹配到的行
    awk '/^UUID/{print $1}' /etc/fstab
    awk '!/^UUID/{print $1}' /etc/fstab
    (3) relational expression:关系表达式:结果有"真"有"假":结果为"真"才会被处理:
    真:结果为非0值,非空字符串:
    awk -F: '$3>=1000{print $1,$3}' /etc/passwd
    awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
    awk -F: '$NF~//bin/bash$/{print $1,$NF}' /etc/passwd
    (4) lineranges: 行范围
    注意:不支持直接给出数字的格式
    startline, endline: /patt1/,/patt2/
    awk -F: '(NR)>=2&&NR<=10{print $1}' /etc/passwd
    (5) BEGIN/END模式
    默认对所有行
    BEGIN{}:仅在开始处理文件中的文本之前执行一次:
    END{}:仅在文本处理完成之后执行一次:
    awk -F: 'BEGIN{print " username | uid ------------"}{print $1,$3}END{print "end======="}' /etc/passwd

    6、常用的action

    (1) Expressions
    (2) control statements 控制语句if,while等
    (3) compund statement:组合语句:
    (4) input statements:
    (5) output statements:

    7、控制语句

    if(condition){statement}
    if(condition){stetement} else {statements}
    while (condition) {statements}
    do{statements} while(condition)
    for(expr1,expr2,expr3){statements}
    break
    continue
    delete array[index]
    delete array
    exit
    { statements }

    7.1 if-else

    语法:if(condition)statement [else statement]
    使用场景:对awk取得的整行或某个字段做条件判断
    用> = < 而不是-eq, -lt

    awk -F: '{if($3>=1000) printf "Username:%s ID:%d ", $1,$3}' /etc/passwd
    awk -F: '{if($3>=1000) {printf "Common user:%s ",$1} else {printf "Root or Sysuser: %s ",$1}}' /etc/passwd
    awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
    df | awk -F% '//dev/sd/{print $1}' | awk '{if($NF>10)print $1,$NF}'

    7.2 while循环

    语法:while(condition) statement
    条件"真",进入循环;条件"假",退出循环
    使用场景:对一行内的多个字段逐一进行类似处理时使用,对数组中的各元素逐一处理时使用
    length()
    awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i);i++}}' /boot/grub2/grub.cfg
    awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /boot/grub2/grub.cfg

    7.3 do-while循环

    语法:do statement while(condition)
    意义:至少执行一次循环体

    7.4 for循环

    语法: for(expr1;expr2;expr3) statement
    for (variable assigement;condition;iteration process){for-body}
    awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /boot/grub2/grub.cfg
    awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){if(length($i)>=7) {print $i,length($i)}}}' /boot/grub2/grub.cfg

    特殊用法:能遍历数组中的所有元素
    语法:for(var in array) {for-body}

    7.5 switch语句

    语法:switch(expression){case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; ... default: statement;}

    7.6 break和continue

    break[n]
    contine(提前结束本轮循环,进入下一轮循环,行内字段间的跳转)

    7.7 next

    控制awk的内生循环,提前结束对本行的处理而直接进入下一行:
    显示ID号为偶数的用户:
    awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd

    8. ARRAY

    关联数组:array[index-expression]
    index-expression:
    (1) 可使用任意字符串,字符串要使用双引号
    (2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为"空串"

    若要判断数组中是否存在某元素,要使用"index in array"格式进行
    若要遍历数组中的每一个元素,要使用for循环:
    for(var in array)(for-body) 注意:var会遍历array的每个索引

    awk 'BEGIN{weekdays["mon"]="Mon";weekdays["tue"]="Tues";print weekdays["mon"]}'
    awk 'BEGIN{weekdays["mon"]="Mon";weekdays["tue"]="Tues";for (i in weekdays)print weekdays[i]}'

    netstat -tan | awk '/^tcp>/{state[$NF]++}END{for(i in state) print i,state[i]}'
    awk '{IP[$1]++}END{for(i in IP)print i,IP[i]}' access_log
    练习:统计/etc/fstab文件系统类型出现的次数
    awk '/^UUID>/{FILESYS[$3]++}END{for(i in FILESYS)print i,FILESYS[i]}' /etc/fstab
    练习:统计/etc/fstab文件中每个单词出现的次数
    awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count)print i,count[i]}' /boot/grub2/grub.cfg

    9. 函数

    9.1 内置函数

    数值处理:
    rand():返回0和1之间的一个随机数
    字符串:
    length([s]):返回指定字符串的长度
    sub(r,s[t]):以r表示模式来查找t所表示的字符串中的匹配的内容,并将其第一次出现替换为s所表示的内容
    echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$0)'
    gsub(r,s[t]):以r表示模式来查找t所表示的字符串中的匹配的内容,并将其所有出现替换为s所表示的内容
    echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$0)'
    split(s,a[,r]):以r为分割符切割字符s,并将切割后的结果保存至a所表示的数组中
    ab -c 100 -n 1000 http://IP

    9.2 自定义函数       

            应用场景少,在此不做过多的阐述

    总结

       适用场景

         对文档的列进行遍历和条件操作,AWK自带行循环,AWK的遍历数组功能特别适合对有共同属性的列进行统计

        awk工作原理和流程

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

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

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

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

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

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

  • 相关阅读:
    iframe如何刷新的三种解决方案
    检查Windows服务是否启动
    关于 wcf 共享端口portSharing
    关于 wcf 异常处理——页面超时
    关于ASP.NET MVC4 Web API简单总结
    关于WCF访问跨越站点获取文件路径的AppDomain方法区别与HttpContext
    DataTable、实体类Model和泛型List之间的转化
    异步load()加载 ckeditor 编辑器
    如何在Eclipse中自动添加注释
    [转]eclipse中编写代码时如何自动提示变量名?
  • 原文地址:https://www.cnblogs.com/liangjindong/p/9050293.html
Copyright © 2011-2022 走看看