• awk命令笔记


    awk是一种可以处理数据、产生格式化报表的语言,功能相当强大。awk的工作方式是读取数据文件,将每一行数据视为一条记录(record),每笔记录以字段分隔符分成若干字段,然后输出各个字段的值。
    awk对每一条记录,都会套用一个"样式{操作}",如果该行符合样式,就执行指定的操作。样式或操作之一,可以省略。如果只有样式,表示要显示符合样式的数据行;如果只有操作,表示对每一数据行都执行该项操作。

    以下是awk常用的作用格式:

    awk"样式"文件:把符合样式的数据行显示出来。

    awk '{操作}' 文件:对每一行都执行{}中的操作。

    awk '样式{操作}' 文件:对符合样式的数据行,执行{}中的操作。

    简单用法:
    awk '/正则/{print $1,$3}' file
    awk -F'[:,]' '/root/{print $1,$3}' passwd #多分隔符
    awk -F'[:,]' '$n~/正则/{print $1}' passwd ~字符等于
    awk -F'[:,]' '$1~/root/{print $0}' passwd
    root:x,0:0:root:/root:/bin/bash


    ~ 匹配,与==相比不是精确比较
    !~ 不匹配,不精确比较
    == 等于,必须全部相等,精确比较
    != 不等于,精确比较
    &&  逻辑与 前面正确了执行
    || 逻辑或 前面错误了执行
    + 匹配时表示1个或1个以上
    == 数字等于
    >= 数字大于等于
    <= 数字小于等于
    awk -F'[:,]' '$3==0 {print $0}' passwd
    root:x,0:0:root:/root:/bin/bash ==数字等于 >=数字等于 <=数字小于

    awk -F'[:,]' '/^root/,$3<2 {print $0}' passwd
    root:x,0:0:root:/root:/bin/bash 以root开头切$3小于2 打印出来


    awk多个判断
    awk -F'[,:]' '$3<1000 &&$3>500 {print $1 " this is system user"}' passwd

    awk双条件判断
    awk -F'[:,]' '/^root/||$3<2 {print $0}' passwd
    root:x,0:0:root:/root:/bin/bash ||或者
    bin:x:1:1:bin:/bin:/sbin/nologin

    awk -F'[:,]' '/^root/&&$3<2 {print $0}' passwd
    root:x,0:0:root:/root:/bin/bash && and

    awk -F'[,:]' '$3>500&&$3<1000{print $0}' passwd $3 小于1000大于500
    admin:x:600:600::/export:/bin/bash
    mysql:x:800:800::/home/mysql:/bin/bash
    www:x:801:801::/home/www:/sbin/nologin
    git:x:802:802::/home/git:/bin/bash

    awk -F'[,:]' '$5 ~/root/ ||$3<2 {print $0}' passwd $5等于root或者$3小于2
    root,x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin

    awk -F'[,:]' '$1 ~ /<r/ {print $0}' passwd 单词铆钉
    awk -F'[:,]' '$5 !~ /r/{print $0}' passwd 不等于
    awk -F'[,:]' '$3==10{print $0}' passwd 等于精确匹配
    awk -F'[,:]' '$1=="ro"{print $0}' passwd
    awk -F'[,:]' '$1=="root"{print $0}' passwd
    root,x:0:0:root:/root:/bin/bash 等于精确匹配

    awk -F'[,:]' '{$3+=2;print $3}' passwd ++$3从2开始每次加1
    ==========================================================================
    awk 打印区间 root和www开头的行
    awk -F'[,:]' '/^ro/,/^ww/' passwd
    root,x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    sync:x:5:0:sync:/sbin:/bin/sync
    admin:x:600:600::/export:/bin/bash
    mysql:x:800:800::/home/mysql:/bin/bash
    www:x:801:801::/home/www:/sbin/nologin
    ==========================================================================
    awk 'BEGIN{}{} END{}' file
    awk 'BEGIN{}/模式/{操作}' file
    awk -F'[,:]' 'BEGIN{print "-----------------------------------------------"}$1~/root/{print $1}' passwd
    -----------------------------------------------
    root
    先执行 BEGING 打印出来-------- 然后匹配模式 $1=root 得 打印出第一段来

    awk内置变量
    FS=变量

    属性 说明
    $0 当前记录(作为单个变量)
    $1~$n 当前记录的第n个字段,字段间由FS分隔
    FS 输入字段分隔符 默认是空格
    NF 当前记录中的字段个数,就是有多少列
    NR 已经读出的记录数,就是行号,从1开始
    RS 输入的记录他隔符默 认为换行符
    OFS 输出字段分隔符 默认也是空格
    ORS 输出的记录分隔符,默认为换行符
    ARGC 命令行参数个数
    ARGV 命令行参数数组
    FILENAME 当前输入文件的名字
    IGNORECASE 如果为真,则进行忽略大小写的匹配
    ARGIND 当前被处理文件的ARGV标志符
    CONVFMT 数字转换格式 %.6g
    ENVIRON UNIX环境变量
    ERRNO UNIX系统错误消息
    FIELDWIDTHS 输入字段宽度的空白分隔字符串
    FNR 当前记录数
    OFMT 数字的输出格式 %.6g
    RSTART 被匹配函数匹配的字符串首
    RLENGTH 被匹配函数匹配的字符串长度
    SUBSEP 34
    RT 把RS记录分割符设置成一个正则,匹配一个或多个数字的字符段为记录分割符。RT就是当RS为正则表达式时的匹配到的每个记录的分割符的内容即为RT变量表示。那么把RT累加给变量s,然后最后输出该值。达到了把所有文本中出现过的数字相加。这里还有一个小细节不要放过,就是 + 号,该符号在BREs正则表达式中是不支持这样写的正确的写法是 + ,但是awk默认是使用的EREs正则表达式,所以支持 + 号的写法,大家注意区分。
    既是RS匹配的内容
    awk -F'[:,]' '{print NR,NF,$1,$NF}' passwd
    1 7 root /bin/bash
    2 7 bin /sbin/nologin
    3 7 daemon /sbin/nologin
    4 7 adm /sbin/nologin
    5 7 lp /sbin/nologin
    6 7 sync /bin/sync
    7 7 admin /bin/bash
    8 7 mysql /bin/bash
    9 7 www /sbin/nologin
    10 7 git /bin/bash
    11 7 redis /bin/bash
    12 7 gogs /bin/bash
    13 7 abc /bin/bash
    14 7 bbb /bin/bash

    awk 'BEGIN{FS="[:,]"}$1~/root/{print $0}' passwd
    root:x,0:0:root:/root:/bin/bash

    awk 'BEGIN{FS="[,:]";"s=0"}{s+=$3}END{print "所有的UID之和是:",s}' passwd
    所有的UID之和是: 6577

    cat abc.log
    1 2 3
    2 3 4

    求和
    awk '{sum+=$3} END {print "Sum = ", sum}' abc.log
    Sum = 7

    求平均值
    awk '{sum+=$3} END {print "Sum = ", sum/NR}' abc.log
    Sum = 3.5
    ==========================================================================
    awk循环
    if(判断1){语句1}
    else if(判断2){语句2}
    awk '/模式/{if(判断1){语句1}}' file

    awk -F'[:,]' '{if($3==0){print $1 " is root"}else if($3<1000){print $1 " is system user"}else if ($3>=1000){print $1"is common user"}}' /etc/passwd


    for循环
    for(变量初始值;变量的范围;增长幅度){命令}
    for(i=1;i<=10;1++){print $3}
    awk -F'[:,]' '{for(i=$3;i<NR;i++) {if($3==0) {print $1 " is root"}else if($3<1000){print $1 " is system user"}else if($3>=1000){print $1 " is common user"}}}' /etc/passwd
    root is root
    bin is system user
    daemon is system user
    adm is system user
    lp is system user
    sync is system user
    shutdown is system user
    halt is system user
    mail is system user


    ==========================================================================
    合并文件

    cat a
    a aaa 1
    b bbb 2
    c ccc 3

    cat b
    a 111 4
    b 222 6
    c 333 5

    awk 'NR==FNR{s[$1]=$0;next}NR!=FNR{print s[$1],$2,$3}' a b
    a aaa 1 111 4
    b bbb 2 222 6
    c ccc 3 333 5

    NR==FNR 匹配第一个文件 NR!=FNR 第二个文件
    s[$1] 设置一个数组将第一个文件的每行当作数组的下标
    next 去除重复


    cat a1
    tom:001
    bob:002

    cat b1
    001:aa
    001:bb
    002:cc
    002:dd

    awk 'BEGIN{FS="[:]"}NR==FNR{s[$2]=$0}NR!=FNR{print s[$1]":"$2}' a1 b1
    tom:001:aa
    tom:001:bb
    bob:002:cc
    bob:002:dd

    思路 先看两个文件 找到相同处 明显是001 将001作为数组的下标
    再次查看发现a文件没有重复的作为数组更好
    所以确定 s[$2] 也就是s[001]
    NR==FNR{s[$2]=$0} 得到的结果就是
    s[001]=tom:001
    s[002]=bob:002
    所以在后面的操作要把b文件的第二段连接上即可

    如果c1的$1和c2的$3相同,c1的$2和c2的$4的后面的三个字符一样,c1的最后一个字段和c2的最后一个字段一样,那么打印c2的这些行
    cat c1
    AAA 001 1000.00
    BBB 001 2000.00
    DDD 002 4000.00
    EEE 002 5000.00
    FFF 003 6000.00

    cat c2
    01 1111 AAA WW001 $$$$ 1000.00
    02 2222 BBB GG001 %%%% 2000.00
    03 3333 CCC JJ001 **** 3000.00
    04 4444 DDD FF002 &&&& 4000.00
    05 5555 EEE RR002 @@@@ 5000.00
    06 666 FFF UU003 JJJJ 6000.00
    07 777 III II005 PPPP 7000.00
    08 8888 TTT TT008 TTTT 8000.00

    awk 'NR==FNR{a[$1]=$1$2$3}NR!=FNR{x=substr($4,3);y=$3x$NF;if(y==a[$3]){print $0}}' c1 c2
    01 1111 AAA WW001 $$$$ 1000.00
    02 2222 BBB GG001 %%%% 2000.00
    04 4444 DDD FF002 &&&& 4000.00
    05 5555 EEE RR002 @@@@ 5000.00
    06 666 FFF UU003 JJJJ 6000.00

    现将相同的取出来 a[$1]=AAA0011000.00 等等 然后比对相同的 先设置变量 将第二个文件的$4的最后三个字符取出来,然后在设置变量y= 设置相同的字段
    要判断是否相同 用if 因为a[aaa] 在第二个文件的第三段所以是a[$3]


    cat d1
    redis:x:497:495::/home/redis:/bin/bash
    gogs:x:1100:1100::/home/gogs:/bin/bash
    abc:x:1101:1101::/home/abc:/bin/bash
    bbb:x:1102:1102::/home/bbb:/bin/bash
    apache:x:48:48:Apache:/var/www:/sbin/nologin

    cat d2
    redis:888888:16631::::::
    gogs:888888:16633:0:99999:7:::
    abc:888888:16661:0:99999:7:::
    bbb:888888:16661:0:99999:7:::
    apache:888888:16707::::::

    awk -F':' 'NR==FNR{a[$1]=$2}NR!=FNR{$2=a[$1];print $0}' d2 d1
    redis 888888 497 495 /home/redis /bin/bash
    gogs 888888 1100 1100 /home/gogs /bin/bash
    abc 888888 1101 1101 /home/abc /bin/bash
    bbb 888888 1102 1102 /home/bbb /bin/bash
    apache 888888 48 48 Apache /var/www /sbin/nologin

    找相同的地方设置数组 发现$1相同 然后下标为要替换的数值 在第一个文件里取出来要替换的数值
    然后在第二个文件里将 $2重新赋值 打印赋值之后的行即可

    发现输出之后的分隔符还是有问题重新定义OFS
    awk 'BEGIN{FS=OFS=":"}NR==FNR{a[$1]=$2}NR!=FNR{$2=a[$1];print $0}' d2 d1
    redis:888888:497:495::/home/redis:/bin/bash
    gogs:888888:1100:1100::/home/gogs:/bin/bash
    abc:888888:1101:1101::/home/abc:/bin/bash
    bbb:888888:1102:1102::/home/bbb:/bin/bash
    apache:888888:48:48:Apache:/var/www:/sbin/nologin

    ==========================================================================
    awk 使用实例

    统计重复连接最多的ip
    netstat -nat|grep ESTABLISHED | awk '{print $5}'|awk -F ':' '{print $1}' | sort | uniq -c | sort -rn | head -n 20

    统计tcp连接状态的个数
    netstat -nat | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

    awk截时间内的取日志
    awk '$3 ~ /11/Aug/2015:12/,/11/Aug/2015:13/' www.xxxxxx.com_access.log

  • 相关阅读:
    关于三次握手与四次挥手你要知道这些
    seafile看不见repo报500错误的解决方法
    VMWare Workstation 配置docker多macvlan网络方法
    利用Python3的dpkt库进行ARP扫描
    关于LAMP配置Let’s Encrypt SSL证书
    OpenSSL生成CA证书及终端用户证书
    CentOS7.2安装Vim8和YouCompleteMe
    CentOS 7.2安装Jenkins自动构建Git项目
    CentOS 7.2 安装Gerrit 2.14.6
    CentOS7.2编译GCC7.3
  • 原文地址:https://www.cnblogs.com/iteemo/p/4890393.html
Copyright © 2020-2023  润新知