zoukankan      html  css  js  c++  java
  • gawk

    awk

    文本处理grep,sed,awk

    字符串处理: 切片,查找替换,查找删除,变量赋值

    grep 文本过滤器 分别有:egrep(等同grep -e),fgrep(最快,不支持正则表达式),grep

    sed  流编辑器,(模式空间,保持空间)

    awk 文本处理报告生成器 (Aho,Werinberger,Kernighan),以定义好的格式输出,在linux上为gawk,之前还有nawk

          数组:declare -a

          关联数组: declare -A

         

    [root@localhost ~]# ls -l /usr/bin/awk 
    lrwxrwxrwx. 1 root root 4 3月  28 20:26 /usr/bin/awk -> gawk

    用法:

      gawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...

      gawk [ POSIX or GNU style options ] [ -- ] program-text file ..

    选项;

    -F 分隔符,可以指定多个,默认空格

    -v 自定义变量

    [root@localhost ~]# awk -v a=b 'BEGIN{print a}'
    b
    [root@localhost ~]# awk  'BEGIN{a="b";print a}'
    b

    输出:

    一. -print

       print item1,item2,...

    1,各项目之间用逗号隔开,而输出以空白字符分隔,如果挨着写,则输出也是挨着,而且可以和print挨着;

    [root@localhost ~]# cat awk.test 
    This is a test
    [root@localhost ~]# awk '{print $1,$2,$3,$4}' awk.test 
    This is a test
    [root@localhost ~]# awk '{print$1$2$3$4}' awk.test 
    Thisisatest

    2,指定分隔符号,在BEGIN模式指定,BEGIN后是花括号,圆括号算语法错误,分隔符号需要用双引号引起来,单引号算语法错误,

    awk: cmd. line:1: BEGIN(OFS="#"){print $1,$2,$3,$4}
    awk: cmd. line:1:      ^ syntax error
    [root@localhost ~]# awk  'BEGIN{OFS="#"}{print $1,$2,$3,$4}' awk.test
    This#is#a#test
    [root@localhost ~]# awk  'BEGIN{OFS='#'}{print $1,$2,$3,$4}' awk.test
    awk: cmd. line:2: BEGIN{OFS=#}{print $1,$2,$3,$4}
    awk: cmd. line:2:           ^ syntax error

    3,可以在输出显示条目之间加入一些其他的输出字符,被当做独立的item,需要用双引号引起来,例如:

    [root@localhost ~]# awk  'BEGIN{OFS="#"}{print $1,$2,"TESTSTRING",$3,$4}' awk.test 
    This#is#TESTSTRING#a#test

    4,可以在输出的条目之间加入换行符,为多行输出:

    [root@localhost ~]# awk 'BEGIN{print "line one
    line two
    line three"}'
    line one
    line two
    line three

    二,awk变量

    awk内置变量之记录变量 (FS,OFS,RS,ORS,NR,NF )

    FS:Field Separator 读取文件时使用的字段分隔符,默认是空白字符

         在BIEGIN'{}'中指定,或者在'{action}'外 -F 指定,如果要指定多个分隔符要用 [] 括起来,字符串还要用引号引起来,可以用正则表达式,当把FS指定为空时,awk会把一行中的每个字符当作一列来处理,awk会将连续的 空格 或 制表符( ) 或 换行符( ) 作为列的分隔符,如果只指定(默认)空格,则多个算空格算一个,如果指定多个分隔符,空白将计数。

    
    [root@localhost ~]# echo '1,2,3' | awk -F , '{print $1}'
    1
    [root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS=","}{print $1}'
    1
    [root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS="[,]"}{print $1}'
    1
    [root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS="[',']"}{print $1}'
    1
    
    错误
    [root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS=,}{print $1}'
    awk: BEGIN{FS=,}{print $1}
    awk:          ^ syntax error
    [root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS=[,]}{print $1}'
    awk: BEGIN{FS=[,]}{print $1}
    awk:          ^ syntax error
    [root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS='[,]'}{print $1}'
    awk: BEGIN{FS=[,]}{print $1}
    awk:          ^ syntax error
    [root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS=[',']}{print $1}'
    awk: BEGIN{FS=[,]}{print $1}
    awk:          ^ syntax error [root@localhost
    ~]# echo '1,2,3' | awk 'BEGIN{FS=[","]}{print $1}' awk: BEGIN{FS=[","]}{print $1} awk: ^ syntax error

    如果要同时指定多个分隔符,且空白开始计数

    [root@localhost ~]# sed -n '13,14p' /etc/passwd
    gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F : '{print $5}' gopher FTP User [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F "[: ]" '{print $5}' gopher FTP [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F "[ :]" '{print $5}' gopher FTP [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F '[ :]' '{print $5}' gopher FTP [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F'[ :]' '{print $5}' gopher FTP [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F' :' '{print $5}' [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F " :" '{print $5}'

     空白计数比较:

    [root@localhost ~]# echo '1,2,3 4  5' | awk 'BEGIN{FS="[ ,]"}{print $3}'
    3
    [root@localhost ~]# echo '1,2,3 4  5' | awk 'BEGIN{FS="[ ,]"}{print $4}'
    4
    [root@localhost ~]# echo '1,2,3 4  5' | awk 'BEGIN{FS="[ ,]"}{print $5}'
    
    [root@localhost ~]# echo '1,2,3 4  5' | awk 'BEGIN{FS="[ ,]"}{print $6}'
    5
    [root@localhost ~]# echo '1,2,3 4  5   6' | awk -v OFS="|" 'BEGIN{FS="[    ,]"}{print $1,$2,$3,$4,$5,$6,$7,$8,$9}'
    1|2|3|4||5|||6
    [root@localhost ~]# echo '1 2 3 4  5   6' | awk -v OFS="|" 'BEGIN{FS=" "}{print $1,$2,$3,$4,$5,$6}'
    1|2|3|4|5|6
    [root@localhost ~]# echo '1 2 3 4  5   6' | awk -v OFS="|" '{print $1,$2,$3,$4,$5,$6}'
    1|2|3|4|5|6

    其他:

    echo '1ab2bc3cd4de5' | awk 'BEGIN{FS="[a-z]+"}{print $1,$2,$5}'
    1 2 5

    OFS:Output Field Separator 输出分隔符

    [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v OFS=" " -F "[ :]" '{print $5,$NF}' 
    gopher /sbin/nologin
    FTP /sbin/nologin
    [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v OFS="" -F "[ :]" '{print $5,$NF}' 
    gopher/sbin/nologin
    FTP/sbin/nologin
    [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v OFS="++" -F "[ :]" '{print $5,$NF}' 
    gopher++/sbin/nologin
    FTP++/sbin/nologin

       如果输出字段之间没有分隔,即print的各字段没有逗号,则在之前OSF定义的输出分隔符不起作用

    [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v OFS="++++" -F "[ :]" '{print $5$NF}' 
    gopher/sbin/nologin
    FTP/sbin/nologin
    [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v OFS="++++" -F "[ :]" '{print $5,$NF}' 
    gopher++++/sbin/nologin
    FTP++++/sbin/nologin

    RS:Record Separator 读取文件时使用的行分隔符,默认换行符为 ,可以指定一个正则表达式为读取换行符

         RT是利用RS匹配出来的内容,如果RS是固定某个值时,RT就是RS的内容

         当RS指定为空时,awk会先自动以多行空格为行分割符号,如果没有空行,就以读取到的所有内容中的空白为分割符

        

    ORS:Output Row Separator 输出换行符,print之间的字段是否有逗号分隔不影响输出换行符的定义和作用

          可以把ORS理解成RS的反过程

    [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v ORS="
    " -F "[ :]" '{print $5,$NF}' 
    gopher /sbin/nologin
    FTP /sbin/nologin
    [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v ORS="++" -F "[ :]" '{print $5,$NF}' 
    gopher /sbin/nologin++FTP /sbin/nologin++[root@localhost ~]# 
    [root@localhost ~]# 

    awk内置变量之数据变量

    NR:Number of input Records ,awk命令所处理的记录数,如果有多个文件,这个数目会把所处理的多个文件统一进行计数

    NF:Number of Field 当前记录的field个数,总数,即容易理解$NF则表示最后一个字段

    [root@localhost ~]# awk '{print NF}' awk.test 
    4

    FNR:与NR不同的是,FNR用于记录正在处理的行是当前这一文件中被处理的行数(如有两个100行的文件,处理到第二各文件的第20行,NR=120,FNR=20)

    [root@localhost ~]# awk '{print NR}' /etc/fstab /etc/issue
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    [root@localhost ~]# awk '{print FNR}' /etc/fstab /etc/issue
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    1
    2
    3

    ARGV:数组,保存命令行本身这个字符串,如awk '{print $0}' awk.test 这条命令中,AVGV[0] 保存awk,AVGV[1] 保存 awk.test

    ARGC:awk命令行的参数个数

    FILENAME:awk命令所处理的文件的名称

    ENVIRON:当前shell环境变量及其值的关联数组:如

    [root@localhost ~]# awk 'BEGIN{print ENVIRON["PATH"]}'
    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

    用户自定义变量(2种方式)

    gawk允许用户自定义变量以便在代码中用到,变量名命名规则和大多数的编程语言相同,只能用字母,数字,和下划线,且不能以数字开头,gawk变量名称区分字符大小写

    a.在脚本中给变量赋值使用赋值语句进行:如

    [root@localhost ~]# awk 'BEGIN{var="variable testing";print var}'
    variable testing

    b,也可以用-v 定义变量,且在awk中,变量不需要加$,在awk中$的意义是字段,在加BEGIN只执行一次,在{}的action中,语句和语句要使用分号隔开

    [root@localhost ~]# awk -v var="varialbe testing" 'BEGIN{print var}'
    varialbe testing

    三,printf的使用

     printf 命令格式: printf format item1,item2...

    1,与print命令最大的不同是,printf需要指定格式

    2,format用于指定后面每一个item的输出格式

    3,printf不会自动打印换行符

    format格式都以%开头(只针对变量格式化

    例如:观察其中输出冒号的位置!

    [root@localhost ~]# awk -F: '{$3>=500?usertype="commom user":usertype="Administrator or System user";printf "%15-s %-s 
    ",$1":",usertype}' /etc/passwd|tail -5
    apache:         Administrator or System user 
    pulse:          Administrator or System user 
    sshd:           Administrator or System user 
    tcpdump:        Administrator or System user 
    Gandefeng:      commom user 

       如果冒号加在格式中:

    [root@localhost ~]# awk -F: '{$3>=500?usertype="commom user":usertype="Administrator or System user";printf "%15-s  :  %-s 
    ",$1,usertype}' /etc/passwd|tail -5
    apache           :  Administrator or System user 
    pulse            :  Administrator or System user 
    sshd             :  Administrator or System user 
    tcpdump          :  Administrator or System user 
    Gandefeng        :  commom user 

    %c 显示字符的ASSII码

    %d ,%i 十进制整数(%+d 表示显示数值符号)

    %e ,%E 科学记数法显示数值

    %f 显示浮点数

    %g,%G 以科学计数法的格式或浮点数的格式显示数值

    %s 显示字符串(%-s 左对齐,默认又对其)

    %u 无符号的整数

    %% 显示百分号自身

    修饰符

    N 显示宽度

    -  左对齐(默认右对齐)

    + 显示数值符号

    四 awk的操作符

    算数操作符

    -x 负值

    +x 转换为数值

    x^y 次方

    x**y 次方

    x/y 除

    x+y 

    x-y

    x%y

    赋值操作符

    =

    +=

    -=

    *=

    /=

    %=

    ^=

    **=

    ++

     --

    需要注意的是 如果某模式为=号 此时使用/*/ 肯能出现语法错误,应以/[=]/ 替代

    布尔值

    awk中,任何非0值或非空字符串都为真,反之就为假比较操作符

    x < y    True if x is less than y

    x <= y  True if x is less or equel to y

    x  > y   True if x is greater than y

    x > = y True if x is greater or equel to y

    x == y  True if x is equel to y

    x !=y    True if x is not equel to y

    x ~ y    True if the string x matches the regexp denoted by y

    x !~y   True if the string x does not match the regexp denoted by y

    表达式间的逻辑关系符

    &&

    ||

    条件表达式

    selector?if-true-exp:if-false-exp

    函数调用

    function_name (paral1,para2)

    awk 常用模式

    1 正则表达式  /regexp/ 

    例如:显示以G开头的用户名

    [root@localhost ~]# awk -F : '/^G/ {print $1}' /etc/passwd
    Gandefeng

    2 表达式,其值为非0或非空字符串时满足条件

    例如:显示使用bash的用户

    [root@localhost ~]# awk -F : '$7~"bash$" {print $1,$7}' /etc/passwd
    root /bin/bash
    Gandefeng /bin/bash

    例如;显示不为nologin的,格式输出

    [root@localhost ~]# awk -F : '$7!~"nologin$" {printf "%-30s%-20s
    ",$1,$7}' /etc/passwd
    root                          /bin/bash           
    sync                          /bin/sync           
    shutdown                      /sbin/shutdown      
    halt                          /sbin/halt          
    Gandefeng                     /bin/bash  

    3 匹配范围

    例如:从第一个以uid为0开头的行到第一个以sync结尾的行

    [root@localhost ~]# awk -F : '$3==0,$7~"sync" {printf "%-30s%-20s
    ",$1,$7}' /etc/passwd
    root                          /bin/bash           
    bin                           /sbin/nologin       
    daemon                        /sbin/nologin       
    adm                           /sbin/nologin       
    lp                            /sbin/nologin       
    sync                          /bin/sync      

    4 BEGIN/END模式,仅在awk的开头前运行一次和命令结束前最后一行处理完之后运行一次

    例如:在上面实例基础上加首行

    [root@localhost ~]# awk -F : 'BEGIN{printf"%-10s%-10s%-20s
    ","name","uid","shell"}$3==0,$7~"sync"{printf "%-10s%-10s%-20s
    ",$1,$3,$7}END{print "end"}' /etc/passwd
    name      uid       shell               
    root      0         /bin/bash           
    bin       1         /sbin/nologin       
    daemon    2         /sbin/nologin       
    adm       3         /sbin/nologin       
    lp        4         /sbin/nologin       
    sync      5         /bin/sync           
    end

    5 空模式 文件的每一行都要做处理

    和尾行,同时匹配,注意需要BEGIN需要在匹配的前面

    6 行限制范围

    [root@localhost ~]# awk -F : '(NR>=1&&NR<=3){print $1}' /etc/passwd
    root
    bin
    daemon

     startline和endline默认匹配最大范围

    [root@localhost ~]# awk -F : '/^r/,/^s/{print $1}' /etc/passwd
    root
    bin
    daemon
    adm
    lp
    sync
    rpc
    vcsa
    rtkit
    abrt
    avahi-autoipd
    saslauth
    rpcuser
    nfsnobody
    haldaemon
    gdm
    ntp
    apache
    pulse
    sshd

    常用的action

    1 expression

    2 control statements

    3 compound statements

    4 input statements

    5 output statements

    五 控制语句

    1 if-else

    if (condition) {then-body} else {[else-body]}

    例如:判断管理员

    awk -F : '{if($1=="root")print $1,"admin";else print $1,"common user"}' /etc/passwd

           格式化输出

     awk -F : '{if($1=="root")printf "%-15s:%s
    ",$1,"admin";else printf "%-15s:%s
    ",$1,"common user"}' /etc/passwd

          统计uid大于500的用户

    [root@localhost ~]# awk -F : -v sum=0 '{if($3>=500) sum++}END{print sum}' /etc/passwd
    13

    2 while

    while (condition){statement1;statement2;...}

    例:显示每一行字符串长度大于等于4的字段

    awk -F : '{i=1;while(i<=NF) {if (length($i)>=4) {print $i};i++}}' /etc/passwd

    3 do-while

    do {statement1,statement2,...} while (condition)

    awk -F : '{i=1;do {print $1,i++}while(i<=3)}' /etc/passwd

    4 for

    for ( variable assignment; condition; iteration process) {statement1,statement2...}

    例:循环3次显示$1 遵循C语言风格

    awk -F : '{for (i=1;i<=3;i++) print $1}' /etc/passwd

    for 还可以遍历数组元素

    例:遍历所有字段显示大于4的字段

    awk -F : '{for (i=1;i<=NF;i++) {if (length($i)>=4) {print $i}}}' /etc/passwd

    5 case

    swith (expression) { case value or /regexp/: statement1,statement2,... default: statement1,....}

    6 break和contiune 用于循环或case语句中的终止或继续

    7 next 提前结束本行文本的处理,并接着处理下一行

     例:显示ID为奇数的用户

    awk -F : '{if($3%2==0) next;print $1,$3}' /etc/passwd

    七 数组

    awk数组的下标从1开始,也可自己定义,可以使用任意字符串作为下标

    例:统计各shell出现次数

    [root@localhost ~]# awk -F : '{shell [$NF]++}END{for(A in shell){print A,shell[A]}}' /etc/passwd
    /bin/sync 1
    /bin/bash 2
    /sbin/nologin 38
    /sbin/halt 1
    /sbin/shutdown 1

    例:统计网络状态

    root@localhost ~]# netstat -tan|awk '/^tcp/{state[$NF]++}END{for (A in state) print A,state[A]}'
    LISTEN 9
    ESTABLISHED 2

    例:统计日志文件IP地址的访问量

    [root@localhost ~]# awk '{counts[$1]++};end {for (url in counts) print counts[url],url}' /var/log/httpd/access_log

     例:9x9乘法表

    [root@localhost ~]# seq 9|sed 'H;g'|awk -v RS='' '{for(i=1;i<=NF;i++){printf"%dx%d=%d%s",i,NR,i*NR,i==NR?"
    ":"	"}}'
  • 相关阅读:
    sed cat 命令
    Datetime 时间模块求日期差
    Selenium:截图显示等待
    SAS常用函数
    SAS笔记
    python 简明教程 【转】
    numpy 笔记
    android Adapter使用详解
    Eclipse的使用技巧之eclipse里的查找:
    Hierarchy Viewer之官方文档翻译之中英对照之未完不续版之使用详解.
  • 原文地址:https://www.cnblogs.com/gandefeng/p/6917020.html
Copyright © 2011-2022 走看看