欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

awk命令的使用

程序员文章站 2022-04-30 14:46:53
...

一、简介

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:无符号整数;
%%: 显示%自身

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

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

如下示例:

[[email protected] ~]# 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判断对应用户是系统用户还是普通用户:

[[email protected] ~]# 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.

三、使用案例

  • 格式化打印当前系统的用户列表
[[email protected] ~]# 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.
[[email protected] ~]# 
  • 搜索打印以/bin/bash为默认shell的用户信息:
[[email protected] ~]# 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地址
[[email protected] ~]# ifconfig | awk '/inet\>/{print $2}'
188.88.88.42
127.0.0.1
192.168.122.1
  • 对比两个文件的内容
[[email protected] tmp]# cat a.sh 
hello,world
i am charlie
this is my linux
magedeu
[[email protected] tmp]# cat b.sh 
1
hello,world
2
i am charlie
3
this is my linux
4
magedeu
[[email protected] 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数组中的元素下标,是的话就打印该行信息。

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

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

如有错误,欢迎指点~