zoukankan      html  css  js  c++  java
  • awk命令

    awk是一个强大的报告生成工具,用于格式化文本输出

    语法:

      awk [options] -f 'program' filename

      program由{ pattern + action statements}组成,动作语句之间用分号“;”分隔

    选项:

      -F:指定输入分隔符

      -v  VAR=value:自定义变量

    常用命令

    1、print

      print item1,item2,......

      item之间用逗号分隔,如果省略item,相当于print $0

    2、变量

      内置变量

        FS:input field seperator,输入分隔符,与-F指定的相同,默认是空白字符 

        OFS:output field seperator,输出分隔符,默认空白字符

    [root@localhost ~]# awk -v FS=: '{print $1}' /etc/passwd 
    root
    bin
    daemon
    adm
    
    [root@localhost ~]# awk -F : '{print $1,$3}' /etc/passwd
    root 0
    bin 1
    daemon 2
    adm 3
    
    
    
    [root@localhost ~]# awk -v FS=: -v OFS=" | " '{print $1,$3}' /etc/passwd
    root | 0
    bin | 1
    daemon | 2
    adm | 3
    lp | 4
    

      RS input record seperator 输入换行符

      ORS output record seperator 输出换行符

    默认的换行符
    依然保留
    [root@localhost ~]# vim num.txt 
    1 a b c
    2 de fg hj
    3
    4
    5
    6
    
    [root@localhost ~]# awk -v RS=" " '{print}' num.txt
    1
    a
    b
    c
    2
    de
    fg
    hj
    
    3
    4
    5
    6
    
    [root@localhost ~]# awk -v RS=" " -v ORS='#' '{print}' num.txt
    1#a#b#c
    2#de#fg#hj#
    3
    4
    5
    6
    #
    

      NF:number of field 字段数量

    打印字段数量
    [root@localhost ~]# awk  '{print NF}' num.txt
    1
    1
    1
    2
    1
    1
    1
    4
    
    打印最后一个字段
    [root@localhost ~]# awk  '{print $NF}' num.txt
    c
    hj
    3
    4
    5
    6
    

     NR: number of record 行数,行号

     FNR: 各文件分别计数

    [root@localhost ~]# awk  '{print NR}' num.txt
    1
    2
    3
    4
    5
    6
    
    多个文件
    [root@localhost ~]# awk  '{print NR}' num.txt /etc/fstab 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    对每个文件单独计数
    [root@localhost ~]# awk  '{print FNR}' num.txt /etc/fstab 
    1
    2
    3
    4
    5
    6
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    

     FILENAME: 当前正在处理的文件名

    体现了awk遍历文件每一行的特性
    [root@localhost ~]# awk  '{print FILENAME}' num.txt /etc/fstab 
    num.txt
    num.txt
    num.txt
    num.txt
    num.txt
    num.txt
    /etc/fstab
    /etc/fstab
    /etc/fstab
    /etc/fstab
    /etc/fstab
    /etc/fstab
    /etc/fstab
    /etc/fstab
    /etc/fstab
    /etc/fstab
    /etc/fstab
    

     ARGC:命令行参数个数

     ARGV:awk参数数组,保存命令行给定的所有参数

    [root@localhost ~]# awk '{print ARGC}' /etc/fstab /etc/issue
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    3
    
    [root@localhost ~]# awk 'BEGIN{print ARGC}' /etc/fstab /etc/issue
    3
    
    [root@localhost ~]# awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/issue
    awk
    [root@localhost ~]# awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/issue
    /etc/fstab
    [root@localhost ~]# awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/issue
    /etc/issue  

     自定义变量

      (1)-v var=value 变量名区分大小写

      (2)在program中定义

    [root@localhost ~]# awk -v test="hello world" 'BEGIN{print test}'
    hello world
    
    [root@localhost ~]# awk 'BEGIN{test="hello world";print test}'
    hello world  
    
    求极值
    [root@localhost ~]# cat num.txt 
    a 1
    b 15
    a 20
    c 6
    d 50
    b 3
    a 7
    
    [root@localhost ~]# awk 'BEGIN{min=999;if ($2 <min) min=$2}END{print "最小值为: ",min}' num.txt 
    最小值为: a
    
    
    
    [root@localhost ~]# awk 'BEGIN{max=0}{if ($2 >max) max=$2 }END{print "最大值为: ",max}' num.txt 
    最大值为: 50

    printf 命令

      格式化输出 printf “FORMAT”,item1,item2,... FORMAT需要为每一个item指定一个格式化符号

      格式符包括:

        %c:显示字符的ASCII码

        %d,%i:显示十进制整数

        %e,%E:科学计数法数值显示

        %f:显示为浮点数

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

        %u:无符号整数

        %s:显示为字符串

        %%:显示%自身

      修饰符:- 表示左对齐 + 表示显示数值符号

    另外打印的时候如果需要打印特殊字符,需要查ASCII码表,对应的十六进制,例如:47------> '  44 ------> $ 46 ---------> &,在某些场景需要使用,比如拼接SQL语句的时候

    [root@localhost ~]# awk -F: '{printf "Username: %s, UID: %d
    ",$1,$3}' /etc/passwd
    Username: root, UID: 0
    Username: bin, UID: 1
    Username: daemon, UID: 2
    Username: adm, UID: 3
    Username: lp, UID: 4
    Username: sync, UID: 5
    
    
    [root@localhost ~]# awk -F: '{printf "Username: %-6s, UID: %d
    ",$1,$3}' /etc/passwd
    Username: root  , UID: 0
    Username: bin   , UID: 1
    Username: daemon, UID: 2
    Username: adm   , UID: 3
    Username: lp    , UID: 4
    Username: sync  , UID: 5
    Username: shutdown, UID: 6
    Username: halt  , UID: 7  

     操作符

    操作符名称 包含的符号
    算术操作符 +、-、*、/、^、%      -x:负值      +x:转换为数值
    赋值操作符 =、+=、-、-=、*=、/=、%= 、++、--
    比较操作符 >,>=、<、<=、!=、==
    模式匹配符

        ~:匹配 、!~:不匹配

    逻辑操作符 &&、||、!
    条件表达式 selector?if-true-expression:if-false-expression
       
    [root@localhost ~]# awk -F: '{$3>1000?usertype="nomal user":usertype="sysadmin or sysuser";printf "%-6s : %s
    ",$1,usertype}' /etc/passwd
    chrony : sysadmin or sysuser
    mysql  : sysadmin or sysuser
    ntp    : sysadmin or sysuser
    test   : sysadmin or sysuser
    test1  : nomal user
    

    pattern

    1、empty:空匹配,匹配每一行

    [root@localhost ~]# awk -F: '{print $1}' /etc/passwd
    root
    bin
    daemon
    adm
    lp
    sync
    shutdown
    halt
    mail
    

    2、/regular expression/:仅处理匹配到的行

    [root@localhost ~]# awk -F '[= ]+' '/^UUID/{print $2}' /etc/fstab 
    0bbd5e50-606c-4c47-8cd7-1ae67f812437
    bba2c917-8540-41c8-97e6-f1d73d9143ba
    1c0f8351-49f0-4dd8-9a8b-1aff1d4a77b0
    

    3、关系表达式:relation expression 返回boolean值,真值被处理,非0或非空为真

    [root@localhost ~]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
    root /bin/bash
    test /bin/bash
    test1 /bin/bash
    
    标准写法~符号后的/匹配字符串/不加引号
    [root@localhost ~]# awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd
    root /bin/bash
    test /bin/bash
    test1 /bin/bash
    

    4、地址定界:awk不支持1,3这样的写法,可以用NR或者使用/pat1/,/pat2/指定地址

    相当于空匹配
    [root@localhost ~]# awk '1,3{print}' /etc/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
    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    halt:x:7:0:halt:/sbin:/sbin/halt
    
    [root@localhost ~]# awk 'NR>1&&NR<=3{print}' /etc/passwd
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    
    [root@localhost ~]# awk '/^a/,/^s/{print}' /etc/passwd
    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
    

    5、BEGIN/END模式

    BEGIN{}:仅在处理文件中的文本之前执行一次
    [root@localhost ~]# awk -F: 'BEGIN{print "------username-------uid----------
    "}{print $1,$3}' /etc/passwd
    ------username-------uid----------
    
    root 0
    bin 1
    daemon 2
    adm 3
    
    当不加BEGIN的时候会对每一行都执行每一条语句
    [root@localhost
    ~]# awk -F: '{print "------username-------uid----------"}{print $1,$3}' /etc/passwd ------username-------uid---------- root 0 ------username-------uid---------- bin 1 ------username-------uid---------- daemon 2 ------username-------uid---------- adm 3 END{}:文本处理完成之后执行一次
    [root@localhost
    ~]# awk -F: '{print "------username-------uid----------"}{print $1,$3}END{print "@@@@@@@@done"}' /etc/passwd ------username-------uid---------- root 0 ------username-------uid---------- bin 1 ------username-------uid---------- daemon 2 ------username-------uid---------- adm 3 @@@@@@@@done 只在文本处理前和语句执行后分别执行BEGIN和END中的语句
    [root@localhost
    ~]# awk -F: 'BEGIN{print "------username-------uid----------"}{print $1,$3}END{print "@@@@@@@@done"}' /etc/passwd ------username-------uid---------- root 0 bin 1 daemon 2 adm 3 @@@@@@@@done 

    常用的action

      (1)expressions  

      (2)控制语句       if、while等

      (3)组合语句

      (4)输入语句

      (5)输出语句

    控制语句

      语法:

        if (condition) {statements} 或者 if (condition) {statements} else {statements}

    [root@localhost ~]# awk -F : '{if ($3>1000) print $1,$3}' /etc/passwd
    test1 1001
    其中,print或printf 是最常用的编辑指令;若有多条编辑指令,可用分号分隔,或者把每一条语句用花括号括起来
    [root@localhost ~]# awk -F : '{if ($3>1000) printf "common_user: %s
    ",$1;else {printf "root or sysuser : %s
    ",$1}}' /etc/passwd
    root or sysuser : postfix
    root or sysuser : chrony
    root or sysuser : mysql
    root or sysuser : ntp
    root or sysuser : test
    common_user: test1
    
    [root@localhost ~]# awk -F : '{if ($3>1000) {printf "common_user: %s
    ",$1} else {printf "root or sysuser : %s
    ",$1}}' /etc/passwd
    root or sysuser : mysql
    root or sysuser : ntp
    root or sysuser : test
    common_user: test1

        while (condition) {statements}

    统计字段长度
    [root@localhost ~]# awk '/[[:space:]]+linux16/ {i=1;while(i<=NF) {print $i,length($i);i++}}' /etc/grub2.cfg 
    linux16 7
    /vmlinuz-3.10.0-862.el7.x86_64 30
    root=UUID=0bbd5e50-606c-4c47-8cd7-1ae67f812437 46
    ro 2
    crashkernel=auto 16
    net.ifnames=0 13
    rhgb 4
    quiet 5
    LANG=en_US.UTF-8 16

    统计字段长度大于5的
    [root@localhost
    ~]# awk '/[[:space:]]+linux16/ {i=1;while(i<=NF) {if (length($i)>5) print $i,length($i);i++}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-862.el7.x86_64 30 root=UUID=0bbd5e50-606c-4c47-8cd7-1ae67f812437 46 crashkernel=auto 16 net.ifnames=0 13 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-1f41634c945240cf95b0a976b07104ea 50 root=UUID=0bbd5e50-606c-4c47-8cd7-1ae67f812437 46 crashkernel=auto 16 net.ifnames=0 13

        do {statements} while (condition)

    [root@localhost ~]# awk '/[[:space:]]+linux16/ {i=1;do {if (length($i)>5) print $i,length($i);i++} while(i<=NF)}' /etc/grub2.cfg 
    linux16 7
    /vmlinuz-3.10.0-862.el7.x86_64 30
    root=UUID=0bbd5e50-606c-4c47-8cd7-1ae67f812437 46
    crashkernel=auto 16
    net.ifnames=0 13
    LANG=en_US.UTF-8 16
    linux16 7
    /vmlinuz-0-rescue-1f41634c945240cf95b0a976b07104ea 50
    root=UUID=0bbd5e50-606c-4c47-8cd7-1ae67f812437 46
    crashkernel=auto 16
    net.ifnames=0 13

        for (expr1;expr2;...;exprn) {statements}

    [root@localhost ~]# awk '/[[:space:]]+linux16/ {for (i=1;i<=NF;i++) print $i,length($i)}' /etc/grub2.cfg 
    linux16 7
    /vmlinuz-3.10.0-862.el7.x86_64 30
    root=UUID=0bbd5e50-606c-4c47-8cd7-1ae67f812437 46
    ro 2
    crashkernel=auto 16
    net.ifnames=0 13
    rhgb 4
    quiet 5
    LANG=en_US.UTF-8 16
    linux16 7
    /vmlinuz-0-rescue-1f41634c945240cf95b0a976b07104ea 50
    root=UUID=0bbd5e50-606c-4c47-8cd7-1ae67f812437 46
    ro 2
    crashkernel=auto 16
    net.ifnames=0 13
    rhgb 4
    quiet 5
    
    [root@localhost ~]# awk '/[[:space:]]+linux16/ {for (i=1;i<=NF;i++) if (length($i)>5) print $i,length($i)}' /etc/grub2.cfg 
    linux16 7
    /vmlinuz-3.10.0-862.el7.x86_64 30
    root=UUID=0bbd5e50-606c-4c47-8cd7-1ae67f812437 46
    crashkernel=auto 16
    net.ifnames=0 13
    LANG=en_US.UTF-8 16
    linux16 7
    /vmlinuz-0-rescue-1f41634c945240cf95b0a976b07104ea 50
    root=UUID=0bbd5e50-606c-4c47-8cd7-1ae67f812437 46
    crashkernel=auto 16
    net.ifnames=0 13

    使用for循环遍历数组元素

      for (var in array)

    switch语句

      语法 switch (expression) {case value1 or /regexp/: statement1;case value1 or /regexp/: statement2;...;default: statement}

    next:提前结束本行的处理,对下一行进行处理

    统计uid为偶数的用户
    [root@localhost ~]# awk -F : '{if ($3%2!=0) next;print $1,$3}' /etc/passwd
    root 0
    daemon 2
    lp 4
    shutdown 6
    mail 8
    games 12
    ftp 14
    systemd-network 192
    sshd 74
    chrony 998
    ntp 38
    test 1000

    数组

    关联数组: array[index]

      索引index

        (1)可以使用任意字符串,但字符串要使用双引号

        (2)如果数组元素不存在,在引用时,awk会自动创建此元素,并将其值初始化为空串

    自定义数组
    [root@localhost ~]# awk 'BEGIN{data["name"]="tom";data["age"]="18";print data["name"]}'
    tom
    
    
    遍历数组中的元素,其中i为数组data的索引,
    [root@localhost ~]# awk 'BEGIN{data["name"]="tom";data["age"]="18"; for (i in data) print data[i]}'
    18
    tom

    [root@localhost ~]# vim num.txt 
    a 1
    b 15
    a 20
    c 6
    d 50
    b 3
    a 7

    统计字母出现的次数 [root@localhost ~]# awk '{a[$1]++}END {for (i in a) print i,a[i]}' num.txt a 3 b 2 c 1 d 1
    统计每个字母对应的数字和 [root@localhost
    ~]# awk '{a[$1]+=$2}END {for (i in a) print i,a[i]}' num.txt a 28 b 18 c 6 d 50

    [root@localhost ~]# awk -F '[ #/:,-=]+' '{for (a=1;a<= NF;a++) {word[$a]++}}END{for (i in word) print i,word[i]}' /etc/fstab
    aff 1
    14
    cd 1
    bba 1
    man 1
    bbd 1

    函数

     内置函数

      字符串处理:length([string]) 返回string的长度

    sub (regular expression, substitution string):

    sub(/regular expression/,"substitution string", target string) 在目标字符串中查找第一个指定匹配的字符串,并替换成指定子串

    awk '{ sub(/test/, "mytest"); print }' testfile
    
    在整个记录中匹配,替换只发生在每行第一次匹配发生的时候。
    
    awk '{ sub(/test/, "mytest", $1); print }' testfile
    
    在整个记录的第一个域中进行匹配,替换只发生在每行第一次匹配发生的时候
    
    
    [root@localhost ~]# echo "0001|20081223efskjfdj|912EREADFASDLKJCV"|awk -F '|' 'BEGIN{ OFS="|" } {sub(/[0-9]+/,"",$2);print $0}'
    0001|efskjfdj|EREADFASDLKJCV
    
    [root@localhost ~]# awk -F: '{sub(/o/,"O",$1);print $1}' /etc/passwd
    rOot
    bin
    daemOn

    gsub (/regular expression/, "substitution string", target string)在整个文档中查找指定字段中所有能匹配指定字符串的字段,并替换成指定子串

    awk '{ gsub(/test/, "mytest"); print }' testfile
    在整个文档中匹配test,匹配的都被替换成mytest。
    
    awk '{ gsub(/test/, "mytest", $1); print }' testfile
    在整个文档的第一个域中匹配,所有匹配的都被替换成mytest。

    [root@localhost ~]# awk -F: '{gsub(/o/,"O",$1);print $1}' /etc/passwd
    rOOt
    bin
    daemOn
    adm
    lp
    sync
    shutdOwn
    halt
    mail
    OperatOr

       split (string, array, "field separator")
       split (string, array)  -->如果第三个参数没有提供,awk就默认使用当前FS值。

    [root@localhost ~]# echo "0001|20081223efskjfdj|EREADFASDLKJCV"|awk '{split($0,a,"|");print a[1],a[2],a[3]}'
    0001 20081223efskjfdj EREADFASDLKJCV

        

  • 相关阅读:
    2018.4.26 lvm
    2018.4.25 github创建新项目
    2018.4.24 快排查找第K大
    2018.4.24 flask_mail使用
    SpringBoot中使用ES和MongoDB常用API
    设计模式-Template_Method模式
    设计模式-Chain of Responsibility模式
    设计模式-Observer模式
    设计模式-Adapter模式
    设计模式-Strategy模式
  • 原文地址:https://www.cnblogs.com/zh-dream/p/12244246.html
Copyright © 2011-2022 走看看