首页 > 代码库 > 文本处理三剑客之gawk
文本处理三剑客之gawk
awk
本章内容:
awk介绍
awk基本用法
awk变量
awk格式化
awk操作符
awk条件判断
awk循环
awk数组
awk函数
调用系统命令
1.awk介绍
★ Linux 文本处理工具三剑客:grep、sed、awk。其中grep是一种文本过滤工具;sed是文本行编辑器,而awk是一种报表生成器,就是对文件进行格式化处理的,但这里的格式化不是文件系统的格式化,而是对文件内容进行各种“排版”,进而格式化显示;
★ 在Linux之上我们使用的是GNU awk 简称gawk,并且gawk就是awk的链接文件,因此系统上使用的awk和gawk是一样的。我们通过man gawk可以获得gawk的相关功能说明---gawk-pattern scanning and processing language(模式扫描及处理语言),gawk是一种过程式编程语言。gawk还支持条件判断、数组、循环等编程语言中所有可以使用的功能,因此还可以把gawk称为一种脚本语言解释器。
1)介绍如下:
★ 文本处理三工具:grep、sed、awk
grep,egrep,fgrep:文本过滤工具:partten
sed:行编辑器;模式空间、保持空间
awk:报告生成器,格式化文本输出;
★ AWK
Aho, Weinberger, Kernighan,报告生成器,格式化文本输出;
有多种版本:New awk(nawk),GNU awk(gawk);
gawk –模式扫描和处理语言;
[root@centos7 ~]# which awk /usr/bin/awk [root@centos7 ~]# ll /usr/bin/awk lrwxrwxrwx. 1 root root 4 Jul 25 23:58 /usr/bin/awk -> gawk★ 基本用法:
awk[options] ‘program’ var=value file…
awk[options] -f programfilevar=value file…
awk[options] ‘BEGIN{ action;… } pattern{ action;… } END{ action;… }‘ file ...
awk程序通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成
用法说明
1)用法格式,选项
★基本格式:awk [options] ‘program‘ file…
·program:PATTERN{ACTION STATEMENT;..},通常是在单引号和双引号中;
·program:编程语言;
·PARTTERN:
模式;部分决定动作语句何时触发及触发事件(BEGIN,END)
·ACTION STATEMENT:
动作语句,可以由多个语句组成,各语句之间使用分号分隔:如print,printf
★options(选项):
-F:指明输入时用到的字段分隔符;
-v var=value: 自定义变量
★分割符、域和记录
·awk执行时,由分隔符分隔的字段(域);标记$1,$2..$n称为域标识。$0为所有域,注意:和shell中变量$符含义不同
·文件的每一行称为记录
·省略action,则默认执行print $0 的操作。
2)awk工作原理
★ 原理:
awk在处理文本时也是一次读取一行文本,然后根据输入分隔符(默认为空格字符)进行切片,切成n个片段,然后将每一片都赋予awk内部的一个变量当中进行保存,这些变量名为$1,$2,$3...等等一直到最后一个,awk就可以对这些片段进行单独处理,比如显示某一段,特定段,甚至可以对某些片段进行额外的的加工处理,比如计数、运算等。
★ 具体工作原理如下:
·第一步:执行BEGIN{action;… }语句块中的语句;
·第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
·第三步:当读至输入流末尾时,执行END{action;…}语句块
·BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中
·END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块
·pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块
举例:
[root@centos7 ~]# tail -5 /etc/fstab # 取 /etc/fstab 的后五行 UUID=5de91e7f-4334-4646-8bcf-7e8df5969f74 / xfs defaults 0 0 UUID=abad3f46-4294-40b0-9d48-78c7e87cbfbf /boot xfs defaults 0 0 UUID=01aef744-48b5-4346-ab7d-33150e05f3c7 /usr xfs defaults 0 0 UUID=9765d553-e77b-48db-a4ff-502e43833384 swap swap defaults 0 0 UUID=a42aca7a-085a-43c2-a22c-4f4aa6a22574 /testdir ext4 acl 0 0 [root@centos7 ~]# tail -5 /etc/fstab |awk ‘{print $2,$3}‘ # 对读进来的每一行都执行打印第2和第3片段 / xfs /boot xfs /usr xfs swap swap /testdir ext4 [root@centos7 ~]# tail -5 /etc/fstab |awk ‘{print "hello",$2,$3}‘ hello / xfs hello /boot xfs hello /usr xfs hello swap swap hello /testdir ext4
输出命令:print
print格式:print item1, item2, ...
要点:
(1) 逗号分隔符;
(2) 输出的各item可以是字符串,也可以是数值、当前记录的字段、变量或awk的表达式;
(3) 如省略item,相当于print $0
演示:
[root@centos7 ~]# awk ‘{print "hello,awk"}‘ # 不管输入什么都只打印定义好的 asdas hello,awk asfas hello,awk dddd hello,awk [root@centos7 ~]# awk -F: ‘{print}‘ /etc/passwd # 把/etc/passwd的每一行都打印一遍 root:x:0:0:tcpdump,,62985600:/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 [root@centos7 ~]# awk -F: ‘{print "tao"}‘ /etc/passwd # /etc/passwd 的每一行输入进去之后都打印成 tao tao tao tao tao [root@centos7 ~]# awk -F: ‘{print $1}‘ /etc/passwd # 以:为分隔符,打印每一行的第一个片段 root bin daemon adm lp [root@centos7 ~]# awk -F: ‘{print $1"\t"$3}‘ /etc/passwd # 也可以用其他分隔符,但一定要加双引号。 root 0 bin 1 daemon 2 adm 3 lp 4 sync 5
awk变量
内置和自定义变量
★内置变量
·FS:输入字段分隔符,默认为空白字符
awk-v FS=‘:‘ ‘{print $1,$3,$7}’ /etc/passwd
awk–F: ‘{print $1,$3,$7}’ /etc/passwd
·OFS:输出字段分隔符,默认为空白字符
awk-v FS=‘:’ -v OFS=‘:’ ‘{print $1,$3,$7}’ /etc/passwd
·RS:输入记录分隔符,指定输入时的换行符,原换行符仍有效
awk-v RS=‘ ‘ ‘{print }’ /etc/passwd
·ORS:输出记录分隔符,输出时用指定符号代替换行符
awk-v RS=‘ ‘ -v ORS=‘###‘‘{print }’ /etc/passwd
·NF:字段数量
awk -F:‘{print NF}’ /etc/fstab, 引用内置变量不用$
awk -F: ‘{print $(NF-1)}‘ /etc/passwd
·NR:行号
awk ‘{print NR}‘ /etc/fstab; awk END‘{print NR}‘ /etc/fstab
·FNR:各文件分别计数,行号
awk ‘{print FNR}‘ /etc/fstab /etc/inittab
·FILENAME:当前文件名
awk ‘{print FILENAME}’ /etc/fstab
·ARGC:命令行参数的个数
awk ‘{print ARGC}’ /etc/fstab /etc/inittab
awk ‘BEGIN {print ARGC}’ /etc/fstab /etc/inittab
·ARGV:数组,保存的是命令行所给定的各参数
awk ‘BEGIN {print ARGV[0]}’ /etc/fstab /etc/inittab
awk ‘BEGIN {print ARGV[1]}’ /etc/fstab /etc/inittab
★自定义变量
·-v var=value
变量名区分字符大小写
·在program中直接定义
awk -v test=‘hello gawk‘ ‘{print test}‘ /etc/fstab
awk -v test=‘hello gawk‘ ‘BEGIN{print test}‘
awk‘BEGIN{test="hello,gawk";print test}‘
内置变量演示:
[root@centos7 ~]# awk -F: ‘{print $1,$3,$7}‘ /etc/passwd # 指明以“:”作为输入字段分隔符,如果不指明的话以空白当做分隔符 root 0 /bin/bash bin 1 /sbin/nologin daemon 2 /sbin/nologin adm 3 /sbin/nologin lp 4 /sbin/nologin [root@centos7 ~]# awk -F: -v OFS=‘=>‘ ‘{print $1,$3,$7}‘ /etc/passwd # 指明输入,输出字段分隔符 root=>0=>/bin/bash bin=>1=>/sbin/nologin daemon=>2=>/sbin/nologin adm=>3=>/sbin/nologin lp=>4=>/sbin/nologin sync=>5=>/bin/sync [root@centos7 ~]# awk -F: -v ORS=‘###‘ ‘{print }‘ /etc/passwd # 指明输出是的换行符 root:x:0:0:tcpdump,,62985600:/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 [root@centos7 ~]# awk -F: ‘{print NF}‘ /etc/passwd # 以:为分隔符,打印每一行的字段数量 7 7 7 7 7 7 7 7 7 [root@centos7 ~]# awk -F: ‘{print $NF}‘ /etc/passwd # 这时,$NF=$7,因为NF为内之变量替换为7 /bin/bash /sbin/nologin /sbin/nologin /sbin/nologin /sbin/nologin [root@centos7 ~]# awk ‘{print NR }‘ /etc/passwd # 显示行号 1 2 3 4 5 6 7 [root@centos7 ~]# awk ‘{print FNR }‘ /etc/fstab /etc/issue 1 # 如果后面跟多个文件的话,要想显示每个文件的行数,变量为FNR,如果不加F,则行号累加 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 [root@centos7 ~]# awk END‘{print NR }‘ /etc/fstab # 显示最后一行的行号 13 [root@centos7 ~]# awk END‘{print FNR }‘ /etc/fstab /etc/issue 6 [root@centos7 ~]# awk ‘{print FILENAME}‘ /etc/fstab # 显示当前文件名 /etc/fstab /etc/fstab /etc/fstab /etc/fstab /etc/fstab /etc/fstab /etc/fstab /etc/fstab [root@centos7 ~]# awk ‘{print ARGC}‘ /etc/fstab /etc/inittab # 命令行参数个数,但会输入的每行都会显示一遍 3 3 3 3 3 [root@centos7 ~]# awk ‘BEGIN {print ARGC}‘ /etc/fstab /etc/inittab 3 # 加上BEGIN 只显示一次命令行参数个数 [root@centos7 ~]# awk ‘BEGIN {print ARGV[0]}‘ /etc/fstab /etc/inittab awk # 数组,显示的是命令行的第几个参数 [root@centos7 ~]# awk ‘BEGIN {print ARGV[1]}‘ /etc/fstab /etc/inittab /etc/fstab [root@centos7 ~]# awk ‘BEGIN {print ARGV[2]}‘ /etc/fstab /etc/inittab /etc/inittab
自定义变量演示:
[root@centos7 ~]# awk -v test=‘hello gawk‘ ‘{print test}‘ /etc/fstab hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk [root@centos7 ~]# awk -v test=‘hello gawk‘ ‘BEGIN{print test}‘ /etc/fstab hello gawk [root@centos7 ~]# awk ‘BEGIN{test="hello,gawk";print test}‘ hello,gawk
输出命令: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
命令演示:
[root@centos7 ~]# awk -F: ‘{printf "%s",$1}‘ /etc/passwd # 显示字符串,默认不自动换行 rootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftpnobodyavahi-autoipdsystemd-bus-proxysystemd-networkdbuspolkitdabrtcolordlibstoragemgmtsetroubleshootrpcrtkitchronytssgeoclueusbmuxdmysqlpulsegdmrpcuserpostfixsshdntpapachetao [root@centos7 ~]# awk -F: ‘{printf "%s\n",$1}‘ /etc/passwd # 添加自动换行符 root bin daemon adm lp sync shutdown halt [root@centos7 ~]# awk -F: ‘{printf "Username: %s\n",$1}‘ /etc/passwd Username: root # 可以添加字符串 Username: bin Username: daemon Username: adm Username: lp Username: sync Username: shutdown [root@centos7 ~]# awk -F: ‘{printf "Username:%s UID:%d\n",$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 [root@centos7 ~]# awk -F: ‘{printf "Username:%15s UID:%d\n",$1,$3}‘ /etc/passwd Username: root UID:0 # 添加修饰符,显示宽度为15字符,默认为右对齐 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 [root@centos7 ~]# awk -F: ‘{printf "Username:%-15s UID:%d\n",$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
操作符
★ 算数操作符:
x+y, x-y, x*y, x/y, x^y(x的y次方), x%y
-x: 转换为负数;
+x: 转换为数值;
★ 字符串操作符:没有符号的操作符,字符串连接;
★ 赋值操作符:
=, +=, -=, *=, /=, %=, ^=
++, --
★ 比较操作符:
>, >=, <, <=, !=, ==
★ 模式匹配符:
~:左边是否和右边匹配包含
!~:是否不匹配
cat /etc/passwd |awk‘$0 ~ /root/‘ |wc -l
cat /etc/passwd |awk‘$0 !~ /root/‘ |wc -l
★ 逻辑操作符:&&,||,!
示例:
awk–F: ‘$3>=0 && $3<=1000 {print $1}‘ /etc/passwd
awk -F: ‘$3 ==0 || $3>=1000 {print $1}‘ /etc/passwd
awk -F: ‘!($3==0){print $1}‘ /etc/passwd
awk -F: ‘!($3>=500) {print $3}}‘ /etc/passwd
★ 函数调用:
function_name(argu1, argu2, ...)
★ 条件表达式:
selector?if-true-expression:if-false-expression
命令演示:
[root@centos7 ~]# awk -F: ‘{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf"%15s:%-s\n",$1,usertype}‘ /etc/passwd root:Sysadmin or SysUser # 显示用户的UID如果大等于1000则为普通用户,否则为管理员或系统用户,并定义格式输出 bin:Sysadmin or SysUser daemon:Sysadmin or SysUser adm:Sysadmin or SysUser lp:Sysadmin or SysUser sync:Sysadmin or SysUser shutdown:Sysadmin or SysUser halt:Sysadmin or SysUser mail:Sysadmin or SysUser operator:Sysadmin or SysUser games:Sysadmin or SysUser ftp:Sysadmin or SysUser nobody:Sysadmin or SysUser avahi-autoipd:Sysadmin or SysUser systemd-bus-proxy:Sysadmin or SysUser systemd-network:Sysadmin or SysUser dbus:Sysadmin or SysUser polkitd:Sysadmin or SysUser abrt:Sysadmin or SysUser colord:Sysadmin or SysUser libstoragemgmt:Sysadmin or SysUser setroubleshoot:Sysadmin or SysUser rpc:Sysadmin or SysUser rtkit:Sysadmin or SysUser chrony:Sysadmin or SysUser tss:Sysadmin or SysUser geoclue:Sysadmin or SysUser usbmuxd:Sysadmin or SysUser mysql:Sysadmin or SysUser pulse:Sysadmin or SysUser gdm:Sysadmin or SysUser rpcuser:Sysadmin or SysUser postfix:Sysadmin or SysUser sshd:Sysadmin or SysUser ntp:Sysadmin or SysUser apache:Sysadmin or SysUser tao:Common User
PATTERN
PATTERN:根据pattern条件,过滤匹配的行,再做处理
(1)如果未指定:空模式,匹配每一行
(2) /regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来
awk‘/^UUID/{print $1}‘ /etc/fstab
awk‘!/^UUID/{print $1}‘ /etc/fstab
(3) relational expression: 关系表达式;结果有“真”有“假”;结果为“真”才会被处理;
真:结果为非0值,非空字符串
假:结果为空字符串
文本处理三剑客之gawk