awk是一个文本工具,通常用于处理数据并生成结果报告
第一种形式:
awk “BEGIN{}pattern{commands}END{}” file_name
或者
standard output | awk ‘BEGIN{} pattern{commands}END{}’
语法格式:
1 2 3 4 |
BEGIN{} 正式处理数据之前执行 pattern 匹配模式 {commands} 处理命令,可能多行 END{} 处理完所有匹配数据后执行 |
内置变量对照表
1 2 3 4 5 6 7 8 9 10 11 12 |
$0 整行内容 $1-$n 当前行的第1-n个字段 NF 当前行的字段个数,也就是多少列 NR 当前行的行号,从1开始计数 FNR 多文件处理时,每个文件行号单独计数,都是从0开始 FS 输入字段分隔符。不指定默认以空格或tab键分割 RS 输入行分隔符。默认回车换行 OFS 输出字段分隔符。默认为空格 ORS 输出行分隔符。默认为回车换行 FILENAME 当前输入的文件名字 ARGC 命令行参数个数 ARGV 命令行参数数组 |
$0获取整行
1 2 3 |
ps -ef |grep nginx |head -n1 |awk '{print $0}' [root@docker-host ~]# ps -ef |grep nginx |head -n1 |awk '{print $0}' root 5866 1 0 12:40 ? 00:00:00 nginx: master process /usr/local/openresty/nginx/sbin/nginx -c /usr/local/openresty/nginx/conf/nginx.conf |
举一个简单例子、获取nginx的master进程id、默认以空格做分隔符
1 2 3 4 |
ps -ef |grep nginx |head -n1 |awk '{print $2}' 这个调命令是以管道符的方式、awk只执行了中间的{commands}方式内置的变量 [root@docker-host ~]# ps -ef |grep nginx |head -n1 |awk '{print $2}' 5866 |
FS Field Separator 字段分隔符,不指定时默认以空格或tab键分隔
不指定分隔符、默认是以空格或tab、注意要用但引号
1 2 3 4 5 6 |
#vim list Hadoop Spark Flume Java Python Scala [root@docker-host sh]# awk '{print $1}' list Hadoop Java |
指定分隔符
1 2 3 4 5 6 |
awk 'BEGIN{FS=":"}{print $1}' /etc/passwd [root@docker-host ~]# awk 'BEGIN{FS=":"}{print $1}' /etc/passwd root bin daemon |
NF Number Field 处理行的字段个数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
vim list Hadoop Spark Flume Java Python Scala go [root@docker-host sh]# awk '{print NF}' list 3 4 用$NF代表文件本身最大字段数。在passwd文件里最大是$7这里。$NF等价于$7 [root@docker-host sh]# awk 'BEGIN{FS=":"}{print $NF}' /etc/passwd /bin/bash /sbin/nologin /sbin/nologin |
NR Number row 处理行的行号
1 2 3 |
[root@docker-host sh]# awk '{print NR}' list 1 2 |
FNR File Number Row 多文件处理时,每个文件单独记录行号
1 2 3 4 5 6 7 8 |
[root@docker-host sh]# awk '{print FNR}' list my.cnf 1 2 1 2 3 .. .. |
RS ROW Separator 输入行分隔符。默认回车换行
1 2 3 4 5 6 7 |
vim list Hadoop|Spark\Flume|Java|Python|Scala\go [root@docker-host sh]# awk 'BEGIN{RS="\\";FS="|"}{print $1}' list Hadoop Flume go |
ORS 输出行分隔符。默认为回车换行
1 2 3 4 5 6 7 8 9 |
vim list Hadoop|Spark\Flume|Java|Python|Scala\go [root@docker-host sh]# awk 'BEGIN{RS="\\";FS="|";ORS="%"}{print $1}' list Hadoop%Flume%go [root@docker-host sh]# awk 'BEGIN{RS="\\";FS="|";ORS="%"}{print $1,$2}' list Hadoop Spark%Flume Java%go % |
OFS 输出字段分隔符。默认为空格
1 2 3 4 5 6 7 8 |
vim list Hadoop|Spark\Flume|Java|Python|Scala\go [root@docker-host sh]# awk 'BEGIN{RS="\\";FS="|";ORS="%";OFS="##"}{print $1,$2}' list Hadoop##Spark%Flume##Java%go ##% |
FILENAME 文件名
1 2 3 4 5 6 7 8 |
vim list Hadoop Spark Flume Java Python Scala go 因为文件有两行、所以输入两行的文件名 [root@docker-host sh]# awk '{print FILENAME}' list list list |
ARGC 命令行参数个数
1 2 3 4 5 6 7 8 9 10 |
[root@docker-host sh]# awk '{print ARGC}' list 2 2 为什么输出2、一个是文件名、还有就是awk本身 [root@docker-host sh]# awk '{print ARGC}' list my.cnf 3 3 3 又添加了一个文件、命令参数增加了一个变成3了 |
awk格式化输出之printf
printf命令的输出,和print不一样。print默认是带格式的。printf则需要自己指定美化字符串。
格式符
1 2 3 4 |
%s 打印字符串 %d 打印10进制数 %f 打印一个浮点数 %c 打印单个字符的ASCII码 |
修饰符
1 2 3 |
- 左对齐 + 右对齐 # 显示8进制在前面加0,显示16进制在前面加0x |
printf和print的对比
1 2 3 4 5 6 7 8 9 |
不带格式 [root@docker-host vagrant]# awk 'BEGIN{FS=":"}{printf $1}' /etc/passwd rootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftpnobodysystemd-networkdbuspolkitdrpcrpcusernfsnobodysshdpostfixchronyvagrantvboxaddsaslauthnscdnslcdmysql[root@docker-host vagrant]# 带格式 [root@docker-host vagrant]# awk 'BEGIN{FS=":"}{print $1}' /etc/passwd root bin daemon |
printf模拟print的输出结果
1 2 3 |
[root@docker-host vagrant]# awk 'BEGIN{FS=":"}{printf "%s\n",$1}' /etc/passwd root bin |
%20s 强制站位20个字符的位置;
1 2 3 4 5 |
[root@docker-host vagrant]# awk 'BEGIN{FS=":"}{printf "%20s %s\n",$1,$7}' /etc/passwd root /bin/bash bin /sbin/nologin daemon /sbin/nologin adm /sbin/nologin |
使用左对齐的方式
1 2 3 4 5 6 7 |
awk 'BEGIN{FS=":"}{printf "%-20s %s\n",$1,$7}' /etc/passwd [root@docker-host vagrant]# awk 'BEGIN{FS=":"}{printf "%-20s %s\n",$1,$7}' /etc/passwd root /bin/bash bin /sbin/nologin daemon /sbin/nologin |
例子
1 2 3 |
1、以字符串格式打印/etc/passwd中的第7个字段,以“:”作为分隔符 awk 'BEGIN{FS=":"} {printf "$s",$7}' /etc/passwd |
1 2 3 4 5 6 7 |
2、以10进制格式打印/etc/passwd中的第三个字段,以“:”作为分隔符 awk 'BEGIN{FS=":"}{printf "%d\n",$3}' /etc/passwd %d参数不能使用+做修饰符、直接用 [root@docker-host vagrant]# awk 'BEGIN{FS=":"}{printf "%10d\n",$3}' /etc/passwd 0 1 2 |
1 2 3 4 5 6 7 8 9 10 11 12 |
3、以浮点数格式打印/etc/passwd中的第3个字段,以“:”作为分隔符 awk 'BEGIN{FS=":"}{printf "%f\n",$3}' /etc/passwd [root@docker-host vagrant]# awk 'BEGIN{FS=":"}{printf "%f\n",$3}' /etc/passwd 0.000000 1.000000 awk 'BEGIN{FS=":"}{printf "%0.2f\n",$3}' /etc/passwd [root@docker-host vagrant]# awk 'BEGIN{FS=":"}{printf "%0.2f\n",$3}' /etc/passwd 0.00 1.00 2.00 |
1 2 3 4 5 6 7 |
4、以16进制数格式打印/etc/passwd中的第3个字段。以":"作为分隔符 awk 'BEGIN{FS=":"} {printf "%#x\n",$3}' /etc/passwd [root@docker-host vagrant]# awk 'BEGIN{FS=":"} {printf "%#x\n",$3}' /etc/passwd 0 0x1 0x2 |
AWK的模式匹配
第一种、模式匹配:RegExp
按正则表达式匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
匹配 /etc/passwd文件行中含有root字符串的所有行 awk 'BEGIN{FS=":"}/root/ {print $0}' /etc/passwd [root@docker-host vagrant]# awk 'BEGIN{FS=":"}/root/ {print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin 匹配 /etc/passwd文件行中以mail开头的所有行 awk 'BEGIN{FS=":"} /^rpc/ {print $0}' /etc/passwd [root@docker-host vagrant]# awk 'BEGIN{FS=":"} /^rpc/ {print $0}' /etc/passwd rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin |
第二种、按关系运算匹配
1 2 3 4 5 6 7 8 |
< 小于 > 大于 <= 小于等于 >= 大于等于 == 等于 != 不等于 ~ 匹配正则表达式 !~ 不匹配正则表达式 |
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
以:为分隔符,匹配/etc/passwd文件中第3个字段小于50的所有行信息 awk 'BEGIN{FS=":"} $3<50 {print $0}' /etc/passwd [root@docker-host vagrant]# awk 'BEGIN{FS=":"} $3<50 {print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin 以:为分隔符,匹配/etc/paswd文件中第3个字段大于50的所有行信息 awk 'BEGIN{FS=":"} $3>50 {print $0}' /etc/passwd 以:为分隔符,匹配/etc/passwd文件中第7个字段为/bin/bash的所有行信息 awk 'BEGIN{FS=":"} $7=="/bin/bash" {print $0}' /etc/passwd [root@docker-host vagrant]# awk 'BEGIN{FS=":"} $7=="/bin/bash" {print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash vagrant:x:1000:1000:vagrant:/home/vagrant:/bin/bash 以:为分隔符,匹配/etc/passwd文件中第7个字段不为/bin/bash的所有行信息 awk 'BEGIN{FS=":"} $7!="/bin/bash" {print $0}' /etc/passwd [root@docker-host vagrant]# awk 'BEGIN{FS=":"} $7!="/bin/bash" {print $0}' /etc/passwd bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin 以:为分隔符,匹配/etc/passwd文件中第3个字段的数字长度至少是3位数的所有行 awk 'BEGIN{FS=":"} $3~/[0-9]{3,}/ {print $0}' /etc/passwd 以:为分隔符,匹配/etc/passwd文件中第1个字段的包含rpc的的所有行 awk 'BEGIN{FS=":"} $1~/rpc/ {print $0}' /etc/passwd [root@docker-host vagrant]# awk 'BEGIN{FS=":"} $1~/rpc/ {print $0}' /etc/passwd rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin 以:为分隔符,匹配/etc/passwd文件中第1个字段的不包含rpc的的所有行 [root@docker-host vagrant]# awk 'BEGIN{FS=":"} $1!~/rpc/ {print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin |
布尔运算符匹配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|| 或 && 与 ! 非 以:为分隔符,匹配/etc/passwd文件的$1字段包含rpc或等于mail的所有行 awk 'BEGIN{FS=":"} $1=="mail" || $1~/rpc/ {print $0}' /etc/passwd [root@docker-host vagrant]# awk 'BEGIN{FS=":"} $1=="mail" || $1~/rpc/ {print $0}' /etc/passwd mail:x:8:12:mail:/var/spool/mail:/sbin/nologin rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin 以:为分隔符,匹配/etc/passwd文件中uid大于60同时gid小于uid awk 'BEGIN{FS=":"} $3>60 && $4<$3 {print $0}' /etc/passwd [root@docker-host vagrant]# awk 'BEGIN{FS=":"} $3>60 && $4<$3 {print $0}' /etc/passwd polkitd:x:999:998:User for polkitd:/:/sbin/nologin chrony:x:998:995::/var/lib/chrony:/sbin/nologin |