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