第一种形式
awk是一个文本工具,通常用于处理数据并生成结果报告
awk "BEGIN{}pattern{commands}END{}" file_name
或者
standard output | awk 'BEGIN{} pattern{commands}END{}'
语法格式:
BEGIN{} 正式处理数据之前执行
pattern 匹配模式
{commands} 处理命令,可能多行
END{} 处理完所有匹配数据后执行
内置变量对照表
$0 整行内容
$1-$n 当前行的第1-n个字段
NF 当前行的字段个数,也就是多少列
NR 当前行的行号,从1开始计数
FNR 多文件处理时,每个文件行号单独计数,都是从0开始
FS 输入字段分隔符。不指定默认以空格或tab键分割
RS 输入行分隔符。默认回车换行
OFS 输出字段分隔符。默认为空格
ORS 输出行分隔符。默认为回车换行
FILENAME 当前输入的文件名字
ARGC 命令行参数个数
ARGV 命令行参数数组
$0获取整行
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、默认以空格做分隔符
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、注意要用但引号
#vim list
Hadoop Spark Flume
Java Python Scala
[root@docker-host sh]# awk '{print $1}' list
Hadoop
Java
指定分隔符
awk 'BEGIN{FS=":"}{print $1}' /etc/passwd
[root@docker-host ~]# awk 'BEGIN{FS=":"}{print $1}' /etc/passwd
root
bin
daemon
NF Number Field 处理行的字段个数
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 处理行的行号
[root@docker-host sh]# awk '{print NR}' list
1
2
FNR File Number Row 多文件处理时,每个文件单独记录行号
[root@docker-host sh]# awk '{print FNR}' list my.cnf
1
2
1
2
3
..
..
RS ROW Separator 输入行分隔符。默认回车换行
vim list
Hadoop|Spark\Flume|Java|Python|Scala\go
[root@docker-host sh]# awk 'BEGIN{RS="\\";FS="|"}{print $1}' list
Hadoop
Flume
go
ORS 输出行分隔符。默认为回车换行
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 输出字段分隔符。默认为空格
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 文件名
vim list
Hadoop Spark Flume
Java Python Scala go
因为文件有两行、所以输入两行的文件名
[root@docker-host sh]# awk '{print FILENAME}' list
list
list
ARGC 命令行参数个数
[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则需要自己指定美化字符串。
格式符
%s 打印字符串
%d 打印10进制数
%f 打印一个浮点数
%c 打印单个字符的ASCII码
修饰符
- 左对齐
+ 右对齐
# 显示8进制在前面加0,显示16进制在前面加0x
printf和print的对比
不带格式
[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的输出结果
[root@docker-host vagrant]# awk 'BEGIN{FS=":"}{printf "%s\n",$1}' /etc/passwd
root
bin
%20s 强制站位20个字符的位置;
[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
使用左对齐的方式
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、以字符串格式打印/etc/passwd中的第7个字段,以“:”作为分隔符
awk 'BEGIN{FS=":"} {printf "$s",$7}' /etc/passwd
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
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
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
按正则表达式匹配
匹配 /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
第二种、按关系运算匹配
< 小于
> 大于
<= 小于等于
>= 大于等于
== 等于
!= 不等于
~ 匹配正则表达式
!~ 不匹配正则表达式
例子
以:为分隔符,匹配/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
布尔运算符匹配
|| 或
&& 与
! 非
以:为分隔符,匹配/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