Linux——文本处理三剑客之awk

awk:报告生成器,对文本内容进行格式化输出,即自定义式的输出文本,显示在终端上。

awk有多种版本:New awk(nawk),GNU awk( gawk)

而Linux中多用gawk,gawk为模式扫描和处理语言。

gawk还是一种过程式编程语言,也称其为脚本语言解释器。

下面使用时,简称awk。

awk在使用时同sed一样,一次处理一行,准确来说,一次处理一个记录,awk 有一个分隔符的功能,

分隔符隔离出一个个记录之后,awk将每个片段赋值给awk内部变量来进行计算、运算、输出等操作。

awk基本用法

1.运行方式:

            (1)  awk + 命令行:awk [options]  'BEGIN{ action;… } pattern{ action;… } END{ action;… }'  filename

1 [root@mmmm(mei) ~]# awk '{print "hello"}' /etc/fstab
2 hello
3 hello
4 hello
5 hello
6 hello
7 hello
8 hello
9 hello

 

 

            (2)  awk + 程序文件  awk [options] ‘program’ var=value file… …

1 [root@mmmm(mei) ~]# awk '{print}' /etc/passwd
2 root:x:0:0:root:/root:/bin/bash
3 dbus:x:81:81:System message bus:/:/sbin/nologin
4 rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
5 rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
6 haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
7 postfix:x:89:89::/var/spool/postfix:/sbin/nologin
8 gdm:x:42:42::/var/lib/gdm:/sbin/nologin

 

 

            (3)  awk + 脚本文件  awk [options] -f programfile filename

 

2.基本格式

awk 程序通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成。

awk 后面可以跟一些选项:
                        -F :指明输入时用到的字段分隔符
                       -f filename :紧跟文件名表示执行该文件

                       -v var=value:自定义变量         

基本格式:awk [options] 'program' filename…

 1 [root@localhost(mei) ~]# awk -F: '{print $1}' /etc/passwd         #以:为分隔符,打印第一列
 2 root
 3 bin
 4 daemon
 5 adm
 6 lp
 7 sync
 8 shutdown
 9 halt
10 mail

program:pattern{action statements;..}

pattern和action:

            pattern部分决定动作语句何时触发及触发事件 BEGIN,END

            action statements对数据进行处理,放在{}内指明 print, printf

分割符、域和记录 :

                       awk执行时,由分隔符分隔的字段(域)标记$1,$2..$n称为域标识 。

                       $0为所有域,如果省略action,则默认执行 print $0 的操作

文件的每一行称为记录,但是这是在默认分隔符为空格下,如果分隔符改变,记录号也随之改变,具体视情况而定。

 

但是具体在执行时是怎样执行的呢?
第一步:执行BEGIN{action;… }语句块中的语句

第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全 部被读取完毕。

第三步:当读至输入流末尾时,执行END{action;…}语句块

            BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块 ,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中 。

           END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的 分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块 。

           pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供 pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取 的每一行都会执行该语句块。


awk变量

变量分为内置和自定义变量。

先介绍内置变量:

        FS:输入字段分隔符,默认为空白字符 。

   

[root@localhost(mei) ~]# awk -F: '{print $1,FS,$3}' /etc/passwd   #内置变量直接使用即可         #-v FS=: == -F:
root :
0 bin : 1 daemon : 2 adm : 3

 

        OFS:输出字段分隔符,默认为空白字符 。

            

1 [root@localhost(mei) ~]# awk -F: -v OFS=":" '{print $1,$3,$7}' /etc/passwd
2 root:0:/bin/bash
3 bin:1:/sbin/nologin
4 daemon:2:/sbin/nologin
5 adm:3:/sbin/nologin
6 lp:4:/sbin/nologin
7 sync:5:/bin/sync

 

        RS:输入记录分隔符,指定输入时的换行符,原换行符仍有效 。

             

1 [root@localhost(mei) ~]# cat fi.txt 
2 aaa.aaa qwwe2.22222
3 dfdj 377474hjd.jhh
4 dsld.lsj2 jfsdfjdsh
5 [root@localhost(mei) ~]# awk -v FS='.' -v RS=" " '{print $1}' fi.txt 
6 aaa
7 qwwe2
8 377474hjd
9 jfsdfjdsh

 

        ORS:输出记录分隔符,输出时用指定符号代替换行符 。

             

1 [root@localhost(mei) ~]# awk -v FS='.' -v RS=" " -v ORS="#" '{print $1}' fi.txt 
2 aaa#qwwe2#377474hjd#jfsdfjdsh

 

        NF:字段数量 。

          

1 [root@localhost(mei) ~]# awk -F: '{print NF}' /etc/passwd
2 7
3 7
4 7
5 7
6 7
[root@localhost(mei) ~]# awk -F: '{print $(NF-1)}' /etc/passwd
/root
/bin
/sbin
/var/adm
/var/spool/lpd

 

        NR:行号 ,但准确的说是记录号。

            

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

 

       FNR:各文件分别计数,行号

            

[root@localhost(mei) ~]# awk '{print FNR}' fi.txt /etc/fstab            # NR也可以进行多个文件计数,但是不再另行进行,FNR则是重新开始
1
2
3
1
2
3
4
5
6
7
8
9
10
11
12
13

  

       FILENAME:当前文件名

          

1 [root@localhost(mei) ~]# awk '{print FILENAME}' /etc/passwd
2 /etc/passwd
3 /etc/passwd
4 /etc/passwd
5 /etc/passwd
6 /etc/passwd

 

       ARGC:命令行参数的个数

            

[root@localhost(mei) ~]# awk 'BEGIN{print ARGC}' /etc/fstab /etc/passwd fi.txt   #参数个数从awk算起,program不算
4

 

       ARGV:数组,保存的是命令行所给定的各参数

            

[root@localhost(mei) ~]# awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/passwd fi.txt 
awk
[root@localhost(mei) ~]# awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/passwd fi.txt 
/etc/fstab

 

 

自定义变量:

        自定义变量(区分字符大小写) (1) -v var=value (2) 在program中直接定义

示例: 

 1 [root@localhost(mei) ~]# awk -v test="haha" '{print test}' /etc/fstab
 2 haha
 3 haha
 4 haha
 5 haha
 6 haha
 7 haha
 8 [root@localhost(mei) ~]# awk -F: '{sex="female";print $1,sex,age;age=21}' /etc/passwd
 9 root female 
10 bin female 21
11 daemon female 21
12 adm female 21
13 lp female 21
14 sync female 21
15 shutdown female 21

 

awk格式化

这里涉及到格式化输出,学习到两个输出命令:print、printf

print:直接输出,用逗号,隔开不同参数即可。

printf:格式化输出,详细介绍如下

printf “FORMAT”, item1, item2, ...

             (1) 必须指定FORMAT

             (2) 不会自动换行,需要显式给出换行控制符,\n

             (3) FORMAT中需要分别为后面每个item指定格式符 

格式符:与item一一对应

              %c: 显示字符的ASCII码 

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

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

            %f:显示为浮点数

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

            %s:显示字符串

            %u:无符号整数

            %%: 显示%自身

修饰符: #[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度

                  %3.1f

                 -: 左对齐(默认右对齐) %-15s

                +:显示数值的正负符号 %+d

1 [root@localhost(mei) ~]# awk -F: '{printf "Username:%-15s UID:%d\n",$1,$3}' /etc/passwd
2 Username:root            UID:0
3 Username:bin             UID:1
4 Username:daemon          UID:2
5 Username:adm             UID:3
6 Username:lp              UID:4

 

awk操作符

算术操作符: x+y, x-y, x*y, x/y, x^y, x%y

                           -x: 转换为负数

                           +x: 转换为数值

字符串操作符:没有符号的操作符,字符串连接

赋值操作符: =, +=, -=, *=, /=, %=, ^= ++, -

比较操作符: ==, !=, >, >=, <, <=

模式匹配符:

                          ~:左边是否和右边匹配包含

                          !~:是否不匹配

                                 eg:awk –F: '$0 ~ /root/{print $1}‘  /etc/passwd

                                          awk '$0~“^root"' /etc/passwd

                                          awk '$0  !~ /root/‘   /etc/passwd

                                          awk –F: ‘$3==0’  /etc/passwd

awk条件判断

逻辑操作符:与&&,或||,非!

示例: 

 1 [root@localhost(mei) ~]# awk -F: '$3 >= 0 && $3 <= 1000 {print $1}' /etc/passwd
 2 root
 3 bin
 4 daemon
 5 adm
 6 lp
 7 sync
 8 shutdown
 9 halt
10 mail
11 operator
12 games
13 ftp
14 nobody
15 [root@localhost(mei) ~]# awk -F: '!($3==0) {print $1}' /etc/passwd
16 bin
17 daemon
18 adm
19 lp
20 sync
21 shutdown
22 halt

函数调用: function_name(argu1, argu2, ...)

条件表达式(三目表达式): selector?if-true-expression:if-false-expression

示例: 

1 [root@localhost(mei) ~]# awk -v FS=: '{$3>=1000?usertype="Common User":usertype="Sys User";printf "UserName:%-15s Type:%s\n",$1,usertype}' /etc/passwd
2 UserName:root            Type:Sys User
3 UserName:bin             Type:Sys User
4 UserName:daemon          Type:Sys User
5 UserName:adm             Type:Sys User
6 UserName:lp              Type:Sys User
7 UserName:sync            Type:Sys User
8 UserName:shutdown        Type:Sys User
9 UserName:halt            Type:Sys User
 1 [root@localhost(mei) ~]# awk -F: 'BEGIN{printf "%-13s%-3s%5s\n","姓名","工资","等级"}{if($3<300){dengji="low"}else if($3>=300 && $3<600){dengji="soso"}else {dengji="high"} {printf "%-15s%-6s%5s\n",$1,$3,dengji}}' /etc/passwd
 2 姓名           工资    等级
 3 root           0       low
 4 bin            1       low
 5 daemon         2       low
 6 adm            3       low
 7 lp             4       low
 8 polkitd        999    high
 9 sssd           998    high
10 libstoragemgmt 997    high
11 rpc            32      low
12 colord         996    high
13 gluster        995    high
14 saslauth       994    high
15 abrt           173     low
16 setroubleshoot 993    high
17 rtkit          172     low

 

posted @ 2018-09-02 20:14  mmm君  阅读(184)  评论(0编辑  收藏  举报