zoukankan      html  css  js  c++  java
  • linux文本处理三剑客之awk

    gawk - pattern scanning and processing language
    awk是指向gawk命令的链接,它的工作模式是对文本逐行进行处理,将每一行按照输入时分隔符切片,每一个切片内容用awk内建的位置变量来存放,然后可以对每一片内容进行输出、循环等操作,不指定输入分隔符时默认分隔符为空白。

    awk基本用法:awk [options] 'program' FILE...
      program: PATTERN{ACTION STATEMENTS},语句之间用分号分隔
    示例:
    [root@localhost scripts]# awk '/^UUID/{print $2,$4}' /etc/fstab
    /boot defaults
    swap defaults
    选项options:
        -F:指明输入时用到的字段分隔符
        -v var=VALUE:自定义变量  
    1.指明输入时字段分隔符为:,打印第1个切片内容,比如对/etc/passwd处理
    [root@localhost scripts]# awk -F: '{print $1}' /etc/passwd
    root
    bin
    daemon
    
    2.使用内建变量FS指明输入时的分隔符为冒号,打印第一个片段内容
    [root@localhost scripts]# awk -v FS=':' '{print $1}' /etc/passwd
    root
    bin
    1.print使用相关要点
        用法:print item1,item2,...
    要点:
    1.itm之间用逗号分隔
    2.输出的各item可以是字符串,也可以是数值
    3.如果省略item,默认print是:print $0,打印整行内容
    1.print后面不跟item时,是将整行内容输出,也即是print $0
    [root@localhost scripts]# awk -F: '{print}' /etc/passwd root:x:0:0:root:/root:/bin/bash
    2.变量
    2.1内建变量
        FS:input field seperator,输入时的分隔符,默认为空白字符
        OFS:output field seperator,输出时的分隔符,默认为空白字符
        RS:input record seperator,输入时的换行符
        ORS:output record seperator,输出时的换行符
        NF:number of field,字段数量
        NR:number of record,行数
        FNR:各文件分别计数:行数
        FILENAME:当前文件名
        ARGC:命令行参数的个数
        ARGV:数组,保存的是命令行所给定的各参数
    内建变量相关示例
    1.FS
    [root@localhost scripts]# awk -v FS=':' '{print $1}' /etc/passwd
    root
    bin
    2.OFS
    [root@localhost scripts]# awk  -v FS=':' -v OFS='@@' '{print $2,$3,$7}' /etc/passwd
    x@@0@@/bin/bash
    x@@1@@/sbin/nologin
    3.RS
    [root@localhost scripts]# awk -v RS='o' '{print $1,$3}' /etc/passwd
    4.ORS
    [root@localhost scripts]# awk -v ORS='##' '{print}' /etc/passwd
    root:x:0:0:root:/root:/bin/bash##bin:x:1:1:bin:/bin:/sbin/nologin##
    5.NF
    显示每行多少段
    [root@localhost scripts]# awk -v FS=: '{print NF}' /etc/passwd
    7
    显示字后一段的值
    [root@localhost scripts]# awk -v FS=: '{print $NF}' /etc/passwd
    /bin/bash
    /sbin/nologin
    6.NR
    [root@localhost scripts]# awk '{print NR}' /etc/passwd
    1
    2
    7.FNR
    
    [root@localhost scripts]# awk '{print FNR}' /etc/fstab /etc/passwd
    1
    2
    3
    4
    5
    1
    2
    3
    8.FILENAME
    [root@localhost scripts]# awk '{print FILENAME}' /etc/fstab
    /etc/fstab
    9.ARGC
    [root@localhost scripts]# awk '{print ARGC}' /etc/fstab
    2
    10.ARGV
    [root@localhost scripts]# awk '{print ARGV[1]}' /etc/fstab
    /etc/fstab
    tips: ARGV[0]: awk ARGV[1]:/etc/fstab
    2.2自定义变量
    1. -v var=value
    [root@localhost scripts]# awk -v test='hello awk' 'BEGIN{print test}'
    hello awk
    [root@localhost scripts]# awk -v test='hello awk' '{print test}' /etc/fstab   此时跟上文件名的作用是显示多少行 
    hello awk
    hello awk 
    2. 在program中直接定义
    [root@localhost scripts]# awk '{test="hello awk";print test}' /etc/fstab
    hello awk
    hello awk 
    3.printf命令
    格式化输出:printf FORMAT,item1,item2,...
    格式符
        %c:显示字符的ASCII码
        %d,%i:显示十进制整数
        %e,%E:科学计数法数值显示
        %f:显示为浮点数
        %g,%G:以科学计数法或浮点形式显示数值
        %s:显示字符串
       %u:无符号整数
       %%:显示%自身
    修饰符
     #[.#]:第一个数字控制显示的宽度,第二个#表示小数点后的精度,比如%3.1f
     默认是右对齐,-:左对齐
     +:显示数值的符号
    相关示例
    [root@localhost scripts]# awk -F: '{printf "ckh%s
    ",$7}' /etc/passwd
    ckh/bin/bash
    ckh/sbin/nologin
    [root@localhost scripts]# awk -F: '{printf "Username:%-15s,UID:%d
    ",$1,$3}' /etc/passwd
    Username:root           ,UID:0
    Username:bin            ,UID:1
    Username:daemon         ,UID:2
    4.操作符
    算术操作符
    x+y,x-y,x*y,x/y,x^y,x%y
    赋值操作符
    =,+=,*=,/=,%=,^=
    ++,--
    比较操作符:
    >,>=,<,<=,!=,==
    模式匹配符
    ~:是否匹配
    !~:是否不匹配
    逻辑操作符
    &&
    ||
    !
    函数调用
        function_name(arg1,arg2,...)
    条件表达式:
        selector?if-true-expression:if-false-expression
    条件表达式示例
    [root@localhost scripts]# awk -v FS=':' '{$3>=500?usertype="common user":usertype="Sysadmin or Sysuser";printf "%15s:%s ",$1,usertype}' /etc/passwd root:Sysadmin or Sysuser bin:Sysadmin or Sysuser
    5.PATTERN
    1. empty:空模式,匹配每一行
    2. /regular expression/:仅处理能够被此处的模式匹配到的行
    [root@localhost scripts]# awk '!/^UUID/{print $1}' /etc/fstab  //以UUID为开头的行之外的行
    #
    #
    3. relational expression:关系表达式,结果有真有假;结果为真才会被处理
        真:结果为非0值,非空字符串
    [root@localhost scripts]# awk -F: '$NF=="/bin/bash"{print $1,$7}' /etc/passwd  //最后一段是/bin/bash的字段
    root /bin/bash
    chengkaihua /bin/bash
    [root@localhost scripts]# awk -F: '$NF~/bash$/{print $1,$7}' /etc/passwd  //以模式匹配bash结尾的片段
    root /bin/bash
    chengkaihua /bin/bash
    4.line ranges:行范围
    startline,endline:/pat1/,/pat2/
    注意:不支持直接给出数字的格式
    [root@localhost scripts]# awk -F: '(NR>=2&&NR<=5){print $1}' /etc/passwd
    bin
    daemon
    5.BEGIN/END模式
    BEGIN{}:仅在开始处理文本之前执行一次
    END{}:仅在文本处理完成之后执行一次
    [root@localhost scripts]# awk -F: 'BEGIN{print "    USERNAME        UID        
    -------------------------------"}{printf "%15s,%10d", $1,$3}END{print "====================
                end"}' /etc/passwd
    6.常用的action
    1.EXPRESSIONS
    2.Control statements:if,while等
    3.Compound statements:组合语句
    4.input statements
    5.output statements
    7.控制语句
    if(condition){statements}
    if(condition){statements}else{statements}
    while(condition){statements}
    do{statements}while(condition)
    for(expr1;expr2;expr3){statements}
    break
    continue
    delete aray[index]
    delete array
    exit
    { statements }
    7.1 if-else
    语法:if(condition)statement[else statement]
    使用场景: 对awk取得的整行或某个字段做条件判断;
    示例:
    id号大于500为普通用户,其他为系统用户
    [root@localhost scripts]# awk -F: '{if($3>=500){printf "Common User:%s ",$1}else{printf "Sysadmin or Sysuser:%s ",$1}}' /etc/passwd Sysadmin or Sysuser:root Sysadmin or Sysuser:bin
    以/bin/bash结尾的字段
    [root@localhost scripts]# awk -F: '{if($NF=="/bin/bash")print $1}' /etc/passwd
    root
    chengkaihua
    每行字段大于5个,则显示整行
    [root@localhost scripts]# awk  '{if(NF>5)print $0}' /etc/fstab
    df命令中use大于百分之20的设备
    # df -h | awk -F% '/^/dev/{print $1}' | awk '{if($NF>20)print $1}' 
    7.2 while循环
    语法:while(condition)statement
    条件为"真",进入循环,条件为"假",退出循环
    使用场景: 对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用

    示例:

    # awk '/^[[:space:]]*/{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
    7.3 do-while循环
    语法:do statement while(condition)
        意义:至少执行一次循环体
    7.4 for循环
    语法:for(expr1;expr2;epr3) statement
    for(variable assignment;iteration process) {for-body}
    特殊用法:
    能够遍历数组中的元素
    语法:for(var in array){for-body}
    # awk '/^[[:space:]]*linux16/{for(i=1;i<NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
    7.5 switch语句
    语法: switch(expression){case VALUE1 or  /REGEXP/;statement... default:statement}
    7.6 break和continue
    break [n]
    continue
    7.7 next
    提前结束对本行的处理而直接进入下一行

    示例:

    显示偶数行
    [root@localhost scripts]# awk -F: '{if($3%2!=0) next;print $1,$3}' /etc/passwd
    root 0
    daemon 2
    lp 4
    8.array
    关联数组:array[index-expression]
    index-expression:
      1.可使用任意字符串
      2.如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为"空串"
      若要判断数组中是否存在某元素,要使用"index in array"格式进行
    给数组赋值:
    weekdays[mon]="Monday"
    给数组赋值并打印第一个值
    [root@localhost scripts]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}'
    Monday
    若要遍历数组中的每个元素,要使用for循环
    for(var in array){for-body}
    [root@localhost scripts]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays){print weekdays[i]}}'
    Monday
    Tuesday
    统计netstat -atn命令结果中各状态结果的出现次数
    [root@localhost scripts]# netstat -atn | awk '/^tcp>/{state[$NF]++}END{for(i in state){print i,state[i]}}'
    ESTABLISHED 2
    LISTEN 8
    [root@localhost tmp]# awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' /tmp/access.log
    192.168.0.11 3
    192.168.0.12 6
    统计/etc/fstab文件中各文件系统类型出现的次数
    [root@localhost ~]# awk '/^UUID/{fs[$3]++}END{for(i in fs){print i,fs[i]}}' /etc/fstab
    swap 1
    ext4 1
    统计指定文件中每个单词出现的次数
    [root@localhost ~]# awk '{for(i=1;i<NF;i++){word[$i]++}}END{for(i in word){print i,word[i]}}' /etc/fstab
    mount(8) 1
    Accessible 1
    pages 1
    reference, 1
    9.函数
    9.1 内置函数
    rand():返回0和1之间一个随机数
    [root@localhost ~]# awk 'BEGIN{print rand()}'
    0.237788
    字符串处理
    length([s]):返回指定字符串的长度
    sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容.也就是将t中的内容r替换为s
      # awk -F: '{print sub(o,O,$1)}' /etc/passwd
    gsub(r,s,[t]):全局替换
    split(s,a[],r):以r为分隔符切割字符串s,并将切割后的结果保存至a所表示的数组中
    注意:awk中的数组从1开始编号
    netstat -atn命令中客户端连接的ip出现次数,采用split分隔符
    [root@localhost ~]# netstat -atn | awk '/^tcp>/{split($5,ip,":");count[ip[1]]++;}END{for(i in count){print i,count[i]}}' 192.168.0.100 3 0.0.0.0 4
    9.2 自定义函数
  • 相关阅读:
    用户需求报告
    结队开发项目——七巧板NABC需求分析
    梦断代码读书笔记3
    课堂练习之环形二维数组
    结对开发之求最大子数组的溢出问题
    《代码之美》第二章读后感(一)
    软件工程项目冲刺阶段二:第五天
    软件工程项目冲刺阶段二:第四天(06-06)
    软件工程项目冲刺阶段二:第三天
    课程评价
  • 原文地址:https://www.cnblogs.com/ckh2014/p/14095686.html
Copyright © 2011-2022 走看看