美文网首页
awk命令的使用

awk命令的使用

作者: 小尛酒窝 | 来源:发表于2018-04-08 15:28 被阅读0次

    一、简介

    awk命令是一种编程语言,用于在linux/unix下对文本和数据进行扫描和处理的工具,其数据来源可以为标准输入、文件、管道等等。awk命令会从第一行输入开始逐行扫描至最后一行,寻找其中匹配特定模式的行,并在相应的行上执行用户指定的操作。Awk命令的基本架构由模式匹配和处理动作组成,默认处理动作为print打印行。

    二、awk命令的使用

    1、命令格式

    gawk [options] 'program...' FILE ...
    

    2、常见选项

    -F fs:指明字段分隔符;
    -v var=value:自定义变量;
    -f programfile:从文件中读取program命令;

    3、program语句

    其program语句的常见格式为:PATTERN{action,statements},其中多个program语句之间通过;分隔。

    • 其中PATTERN格式为:
      1)empty:空模式,表示匹配每一行,如:awk -F: '{print $1,$3}' /etc/passwd 表示以:为分隔符,打印每行的第一和第三个字段 。
      2)/regular expression/:仅处理能够被此模式匹配到的行,如:awk -F: '/^root/{print $1,$3}' /etc/passwd,表示以:为分隔符,打印以root开头的行的第一和第三个字段;
      3)/PATTERN1/,/PATTERN2/:表示仅处理从第一个被pattern1匹配到行,到第一个被pattern2所匹配的行之间的所有行,如:awk -F: '/root/,/shutdown/{print $1,$3}' /etc/passwd,表示以:为分隔符,打印从第一个以root开头的行到第一个以shutdown开头的行之间的所有行的第一和第三个字段。
      4)relation expression:使用关系表达式进行匹配,只有结果会真的行才会被处理,如:awk -F: '(NR>=10&&NR<=20){print $1,$3}' /etc/passwd,表示以:为分隔符,打印10-20行的第一和第三个字段;
      5)BEGIN{}和END{}
      BEGIN{}:表示在开始处理行前执行一次指定的操作;
      END{}:表示在结束对行的处理后执行一次指定的操作;
      如:awk -F: 'BEGIN{print "This is the begin."};{print $1,$3};END{print "This is the end."}' /etc/passwd,表示在执行行打印操作前,先打印指定的字符串"This is the begin.",在执行行打印操作后再打印字符串“This is the end.”
    • program语句的变量
      program中内置了一些变量,在编写program语句时能够直接调用相应的变量,进而简化语句。调用内建变量时无需加$

    FS:输入字段分隔符,默认为空白字符;
    OFS:输出字段分隔符,默认为空白字符;
    RS:输入时的换行符;
    ORS:输出时的换行符;
    NF:每行的字段数,$NF表示最后一个字段;
    NR:表示行数;
    FNR:若提供多个文件,则分别计算各文件的行数;
    FILENAME:当前文件名;
    ARGC:命令行参数的个数;
    ARGV:参数数组,保存的是命令行给定的各参数;

    另外也可以在awk命令中自定义相关的变量,可以使用-v选项自定义变量,也可以在语句当中进行赋值操作,如:awk 'BEGIN{test="hello awk"; print test}'、ls -l | awk '/root/{hello="this is a test.";print $3,hello}'

    • action
      常见的action动作有:print、printf
      1)print命令
      其使用格式类似于print item1,item2,...,使用逗号作为分隔符,输出的item可以为字符串,也可以为数值,也可以为当前记录的字段、变量或表达式等。如果省略了item,则相当于print $0打印所有行。
      2)printf命令
      printf命令常用于格式化输出awk命令的执行结果信息。其格式类似于printf FORMAT,item1,item2...,其中必须指定FORMAT格式;如需换行,需手动添加\n换行符;在FORMAT中需要分别为后面的每个item指定一个格式符。
      其对应的格式符有:

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

    其中还可以使用以下修饰符对格式符进行输出格式的整理:

    #[.#]:第一个#数字控制格式符显示的宽度;第二个#数字表示格式符显示的内容的精确度,只显示最大长度为#的格式符内容;
    -:左对齐,默认为右对齐;
    +:显示数值的符号;

    如下示例:

    [root@localhost ~]# awk -F: '{printf "The user:%-20s User ID:%15d\n",$1,$3} ' /etc/passwd
    The user:root                 User ID:              0
    The user:bin                  User ID:              1
    The user:daemon               User ID:              2
    The user:adm                  User ID:              3
    The user:lp                   User ID:              4
    The user:sync                 User ID:              5
    The user:shutdown             User ID:              6
    The user:halt                 User ID:              7
    The user:mail                 User ID:              8
    The user:operator             User ID:             11
    The user:games                User ID:             12
    The user:ftp                  User ID:             14
    The user:nobody               User ID:             99
    The user:avahi-autoipd        User ID:            170
    The user:systemd-bus-proxy    User ID:            999
    The user:systemd-network      User ID:            998
    The user:dbus                 User ID:             81
    The user:polkitd              User ID:            997
    The user:tss                  User ID:             59
    The user:postfix              User ID:             89
    The user:sshd                 User ID:             74
    
    • 条件表达式
      awk命令的program语句也支持通过条件表达式来判断控制,其表达式支持常见的算术、赋值、比较等操作符,如:+,-,*,/,%,=,+=,>,<,~等等的操作符,也支持逻辑操作与或非,其格式为:

    awk [optioins] '{selector?if-true-expression:if-false-expression;action statements}' /PATH/TO/SOMEFILE

    如根据用户ID判断对应用户是系统用户还是普通用户:

    [root@localhost ~]# awk -F:  '{$3>=1000?usertype="this is a common user.":usertype="This is a system user.";printf "%20s:%-s\n",$1,usertype}' /etc/passwd
                    root:This is a system user.
                     bin:This is a system user.
                  daemon:This is a system user.
                     adm:This is a system user.
                      lp:This is a system user.
                    sync:This is a system user.
                shutdown:This is a system user.
                    halt:This is a system user.
                    mail:This is a system user.
                operator:This is a system user.
                   games:This is a system user.
                     ftp:This is a system user.
                  nobody:This is a system user.
                 pegasus:This is a system user.
           avahi-autoipd:This is a system user.
                     ods:This is a system user.
       systemd-bus-proxy:This is a system user.
         systemd-network:This is a system user.
                    dbus:This is a system user.
                 polkitd:This is a system user.
                    sssd:This is a system user.
                  apache:This is a system user.
    

    三、使用案例

    • 格式化打印当前系统的用户列表
    [root@localhost ~]# awk -F: 'BEGIN{print "User lists"};{printf "User:%-25s\n",$1};END{print "This is the end."}' /etc/passwd
    User lists
    User:root                     
    User:bin                      
    .....  
    User:nologin                  
    User:hadoop                   
    This is the end.
    [root@localhost ~]# 
    
    • 搜索打印以/bin/bash为默认shell的用户信息:
    [root@localhost ~]# awk -F: '$7~/.*bash\>/{print $0}' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    amandabackup:x:33:6:Amanda user:/var/lib/amanda:/bin/bash
    postgres:x:26:26:PostgreSQL Server:/var/lib/pgsql:/bin/bash
    centos:x:1001:1001::/home/centos:/bin/bash
    federo:x:1002:1002::/home/federo:/bin/bash
    counter:x:1003:1004::/home/counter:/bin/bash
    charlie:x:1004:1005::/home/charlie:/bin/bash
    Jone:x:1006:1007::/Jone:/bin/bash
    Williom:x:1200:1005::/home/Williom:/bin/bash
    mageia:x:1100:1100::/home/linux:/bin/bash
    bash:x:2003:2003::/home/bash:/bin/bash
    testbash:x:2004:2004::/home/testbash:/bin/bash
    basher:x:2005:2005::/home/basher:/bin/bash
    hadoop:x:2007:2007::/home/hadoop:/bin/bash
    
    • 获取系统网卡的Ip地址
    [root@localhost ~]# ifconfig | awk '/inet\>/{print $2}'
    188.88.88.42
    127.0.0.1
    192.168.122.1
    
    • 对比两个文件的内容
    [root@localhost tmp]# cat a.sh 
    hello,world
    i am charlie
    this is my linux
    magedeu
    [root@localhost tmp]# cat b.sh 
    1
    hello,world
    2
    i am charlie
    3
    this is my linux
    4
    magedeu
    [root@localhost tmp]# awk 'FNR==NR{a[$0];next}{if($0 in a)print $0}' a.sh b.sh
    hello,world
    i am charlie
    this is my linux
    magedeu
    

    上述awk命令在FNR和NR的等式成立的时候,将文件a.sh每行的内容作为数组a下标,然后执行next跳过后续if判断语句;当FNR和NR的等式不成立的时候,不执行a[$0];next,执行后面的if语句,判断b.sh中的每行内容是否为a数组中的元素下标,是的话就打印该行信息。

    同理,利用取反找出不同的行:

    [root@localhost tmp]# awk 'FNR==NR{a[$0];next}{if (!($0 in a))print $0}' a.sh b.sh
    1
    2
    3
    4
    
    • 从文件中读取program语句执行awk命令
      这里以上面文件对比的命令为例:
    [root@localhost tmp]# cat awk.sh 
    FNR==NR{
        a[$0];
        next
    }
    {
        if (!($0 in a))
        print $0
    }
    [root@localhost tmp]# awk -f awk.sh a.sh b.sh
    1
    2
    3
    4
    

    如有错误,欢迎指点~

    相关文章

      网友评论

          本文标题:awk命令的使用

          本文链接:https://www.haomeiwen.com/subject/fkjyhftx.html