AWK是一种处理文本文件的语言,是一个强大的文本分析工具。
举例:
1.所在路径
[root@centos7 ~]#ll `which awk`
lrwxrwxrwx. 1 root root 4 May 10 13:05 /usr/bin/awk -> gawk
2.基本用法
awk '{print $1}' /etc/fstab -- $1指的是第几列。
举例:awk '{print 20*10}'
3.可以由3部分组成
BEGIN{print }{print}END{print} --BEGIN和END决定了各自的语句在第几行。
举例: [root@centos7 data]#awk 'BEGIN{print "number"}{print 20*10}END{print "the end"}' fstab
number
200
200
200
200
the end
4. -F "分隔符" $0整行,$1第一列
awk -F ":" '{print $1"\t" $3}' passwd
5.1 FS:输入字段分隔符,默认为空白字符
(1)基本用法 awk -v FS=':' '{print $1,FS,$3}’ /etc/passwd
方便之处在于如果之前定义好了变量可以直接调用
[root@centos7 data]#fs=":"
[root@centos7 data]#awk -v FS=$fs '{print $1 FS $2}' passwd
(2)指定范围 第一种 df|awk -F ' +|%' '{print $1,$5}
第二种 awk -F "[ |\[]" '{print $5}' access_log
awk -F "[ []" '{print $5}' access_log
5.2 OFS:输出字段分隔符,默认为空白字符
awk -F "[ []" -v OFS="--" '{print $1,$5}' access_log |head -10
172.18.118.91--20/May/2018:08:09:59
172.18.118.91--20/May/2018:08:09:59
5.3 RS :输入记录分隔符,指定输入时的换行符
awk -v RS=' ' ‘{print }’ /etc/passwd
[root@centos7 data]#cat awktest
a,b,c
d;e,f
gg;hh;xx
asd
默认把';'分割看作一行
[root@centos7 data]#awk -F "," -v RS=';' '{print $1}' awktest
a
e
hh
xx
asd
5.4 ORS:输出记录分隔符,输出时用指定符号代替换行符
awk -v RS=' ' -v ORS='###'‘{print }’ /etc/passwd
[root@centos7 data]#awk -F "," -v ORS='-----' '{print $1,$2}' awktest
a b-----d;e f-----gg;hh;xx -----asd -----
5.5 NF:字段数量
awk -F:‘{print NF}’ /etc/fstab 引用变量时,变量前不需加$
awk -F:‘{print $(NF-1)}' /etc/passwd
awk -F":" '{print $(NF)}' passwd 取最后一行
5.6 NR:记录号
awk ‘{print NR}’ /etc/fstab ; awk END‘{print NR}’ /etc/fstab
awk '{print NR, $1}' passwd 加行号
5.7 FNR:各文件分别计数,记录号
awk '{print FNR}' /etc/fstab /etc/inittab --这样会对每个文件从头编号
passwd 1 libstoragemgmt
passwd 2 colord
passwd 3 rpc
passwd 4 gluster
fstab 1 /dev/sda1 /boot xfs defaults 0 0
fstab 2 /dev/sda2 / xfs defaults 0 0
5.8 FILENAME:当前文件名
awk '{print FILENAME}’ /etc/fstab
awk -F":" '{print FILENAME,FNR,$1}' passwd fstab
5.9 ARGC:命令行参数的个数
awk '{print ARGC}’ /etc/fstab /etc/inittab
awk ‘BEGIN {print ARGC}’ /etc/fstab /etc/inittab
5.10 ARGV:数组,保存的是命令行所给定的各参数
awk ‘BEGIN {print ARGV[0]}’ /etc/fstab /etc/inittab
awk ‘BEGIN {print ARGV[1]}’ /etc/fstab /etc/inittab
5.11 自定义变量(区分字符大小写)
(1) -v var=value
(2) 在program中直接定义
[root@centos7 data]#awk -v NAME='magedu' 'BEGIN{print NAME}'
magedu
可以直接调用文件
[root@centos7 data]#echo '{print $1,$3}' > f1.awk
[root@centos7 data]#awk -F: -f f1.awk passwd fstab
root 0
bin 1
daemon 2
adm 3
lp 4
6 printf
printf 格式 $1,$2
%c:显示字符的ASCII码
%d, %i:显示十进制整数
%e, %E:显示科学计数法数值
%f:显示为浮点数
%g, %G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%:显示%自身
#[.#] 第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f
- 左对齐(默认右对齐) %-15s
+ 显示数值的正负符号 %+d
echo "aaa:123.456"|awk -F: '{printf "%-10s %10.1f" ,$1,$2}'
[root@centos7 data]#awk -v NAME='magedu' 'BEGIN{print NAME}'
magedu
打印表格
awk -F: 'BEGIN{print "---------------------------------\nusername |uid |\n----------------------"}{printf "%-20s | %8d |\n-----------------------------------\n",$1,$3}' passwd
支持运算
x+y, x-y, x*y, x/y, x^y, x%y
- x:转换为负数
+x:将字符串转换为数值
赋值
=, +=, -=, *=, /=, %=, ^=,++, --
比较操作符:
==, !=, >, >=, <, <=
awk -F: '$3==996''{print $1,$3}' passwd --中间不许有空格。
模式匹配符:
~:左边是否和右边匹配,包含
!~:是否不匹配
awk -F: '$1 ~ "rpc"''{print $1,$3}' passwd
awk -F: '! ($1 ~ "rpc")''{print $1,$3}' passwd
逻辑操作符:与&&,或||,非!
#awk -F: '! ($1 ~ "rpc")&& $3 <100''{print $1,$3}' passwd
条件表达式(三目表达式)
selector?if-true-expression:if-false-expression
awk -F: '$3<=100?line="less":line="more" {print line, $1,$3}' passwd
支持正则表达式
awk -F: '/mail/{print $1,$3}' passwd --找出mail的行
continue;break
跳过5:awk 'BEGIN{for(i=0;i<10;i++){if (i==5) continue;print i}}'
到5直接跳出 awk 'BEGIN{for(i=0;i<10;i++){if (i==5) break;print i}}'
数组
awk 'BEGIN{num["a"]=1;num["b"]=2;num["c"]=3;print num["b"]}'
99.实例
取访问最多的ip
awk '{print $1}' access_log |sort |uniq -c|sort -nr|head -3
取基数
seq 10 |awk 'i=!i'
取偶数
seq 10 |awk '!(i=!i)'
取ip
ifconfig ens33|awk '/netmask/{print $2}
取3-7行
seq 10|awk 'NR >2 && NR < 8'
取指定范围的行
awk -F: '/ftp/,/rpc/{print $1}' passwd
取大于10的行
df|awk -F ' +|%' '/\/dev\/sd/{ if($5>10)print $1,$5}'
while练习
awk '/linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /boot/grub2/grub.cfg
100之内数相加
awk 'BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i};print sum}'
打印ip出现的次数 ip[$1]++ 以第一列为下标
awk '{ip[$1]++}END{for (i in ip){print i,ip[i]}}' access_log