1.Awk基础介绍
2.awk语法格式
第一种形式:awk 'BEGIN{} pattern {commands} END {}' file_name
第二种形式:standard output | awk BEGIN{} pattern {commands} END {}
第三种形式:awk [options] -f awk-script-file filenames
2.Awk工作原理
1.awk将文件中的每一行作为输入, 并将每一行赋给内部变量$0, 以换行符结束
2.awk开始进行字段分解,每个字段存储在已编号的变量中,从$1开始[默认空格分割]
3.awk默认字段分隔符是由内部FS变量来确定, 可以使用-F修订
4.awk行处理时使用了print函数打印分割后的字段
5.awk在打印后的字段加上空格,因为$1,$3 之间有一个逗号。逗号被映射至OFS内部变量中,称为输出字段分隔符, OFS默认为空格.
6.awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕.
3.Awk内部变量
$0 #将读入进来的一行数据存储至$0中,读入进来默认按行为分割由RS变量控制
$1 #经过FS变量字段分割后,将一行内容拆分成几段,分别赋值给$1 $2 $3.....
NF #统计每一行由FS分割之后多少列,多少个字段
NR #给每一行载入进来的内容,都添加一个编号
FS #指定字段分隔符,默认空格为分割
RS #指定读入进来的内容分隔符,默认按照 \n 换行符
OFS #输出字段分割符,默认是空格为分割
ORS #输出行分割符,默认是换行
print #打印
4.Awk格式输出
printf 格式符 含义 %s 打印字符串 %d 打印十进制数 %f 打印一个浮点数 %x 打印十六进制数 %o 打印八进制数 修饰符 含义 - 左对齐 + 右对齐
[root@manager awk]# awk '
BEGIN {
printf "%-20s%-20s%-20s%-20s\n",
"Name","shuxue","yuwen","yinx"
}
{
printf "%-20s%-20s%-20s%-20s\n", $1,$2,$3,$4
}' file3.txt
Name shuxue yuwen yinx
Oldxu 20 30 40
oldqiang 10 5 2
oldguo 1 1 1
oldgao 1 2 3
oldboy 10 2 0
5.Awk模式匹配
1.正则匹配
2.运算符 < > +-/*
3.与或非
符号 含义
< 小于
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3>50{print $0}' passwd
3、以:为分隔符,匹配/etc/passwd文件中第7个字段为/bin/bash的所有行信息
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' passwd
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$7 ~/\/bin\/bash/{print $0}' passwd
4、以:为分隔符,匹配/etc/passwd文件中第7个字段不为/bin/bash的所有行信息
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$7!="/bin/bash"{print $0}' passwd
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$7 !~/\/bin\/bash/{print $0}' passwd
5、以:为分隔符,匹配/etc/passwd文件中第3个字段包含3个数字以上的所有行信息
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3 ~ /[0-9]{3,}/{print $0}' passwd
布尔运算符匹配示例
符号 含义
|| 或
&& 与
! 非
1、以:为分隔符,匹配passwd文件中包含ftp或mail的所有行信息。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$1=="ftp"||$1=="mail"{print $0}' passwd
2、以:为分隔符,匹配passwd文件中第3个字段小于50并且第4个字段大于50的所有行信息。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3<50 && $4>50{print $0}' passwd
3.匹配没有/sbin/nologin 的行。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"} $0 !~ /\/sbin\/nologin/{print $0}' passwd
[root@manager awk]# awk 'BEGIN{FS=":"} $7 != "/sbin/nologin"' passwd
a
wk的 + - * / % 支持小数
运算符 含义
+ 加
- 减
乘
/ 除
% 余
[root@manager awk]# cat student.txt
oldxu 80 90 96 98
oldqiang 93 98 92 91
oldguo 78 76 87 92
oldli 86 89 68 92
oldgao 85 95 75 90
本章练习示例:
1.找出/etc/passwd文件中uid为0的。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3==0' passwd
2.找出/etc/passwd文件中uid小于10的。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3<10' passwd
3.找出/etc/passwd文件中uid 小于50,且bash为/bin/bash 的行
awk 'BEGIN{FS=":"} $3<50 && /\/bin\/bash$/' passwd
awk 'BEGIN{FS=":"} $3<50 && $7 == "/bin/bash"' passwd
4.匹配用户名为root并且打印uid小于15的行
awk 'BEGIN{FS=":"} $3<15 && $1=="root"' passwd
5.匹配用户名为root或uid大于5000
awk 'BEGIN{FS=":"} $3>5000 || $1=="root"' passwd
6.匹配uid为3位及以上的行
awk 'BEGIN{FS=":"} $3 ~ /[0-9]{3,}/' passwd
7.匹配到 /sbin/nologin 的行
awk '$0 ~ /\/sbin\/nologin/' passwd
awk 'BEGIN{FS=":"} $7 ~ "/sbin/nologin" passwd
awk 'BEGIN{FS=":"} $7 == "/sbin/nologin" passwd
8.磁盘使用率大于多少35092400,则打印可用的值。
df |awk 'NR==2 { if ($4 < 35092400) {print $4} }
9.正则匹配nginx开头的行
awk '!/^#|^$|^ +#/' /etc/nginx/nginx.conf
翻译如下语句含义:
示例1
awk '/west/' datafile #从datafile文件中匹配west行
awk '/^nor/' datafile #从datafile文件中匹配以nor开头的行
awk '$3 ~ /^nor/' datafile
awk '/^(no|so)/' datafile
awk '{print $3,$2}' datafile
awk '{print $3 $2}' datafile
awk '{print $0}' datafile
awk '{print "Number of fields: "NF}' datafile
awk '/nor/{print $3,$2}' datafile
awk '/^[ns]/{print $1}' datafile
awk '$5 ~ /\. [7-9]+/' datafile
awk '$2 !~ /E/ {print $1,$2}' datafile
awk '$3 ~ /^job/{print $3 "is a nice boy."}' datafile
awk '$8 ~ /[0-9][0-9]$/{print $8}' datafile
awk '$4 ~ /Cn$/{print "The price is $" $8 "."}' datafile
awk '/gdx/{print $0}' datafile
awk -F: '{print "Number of fields: "NF}' /etc/passwd
awk -F"[ :]" '{print NF}' /etc/passwd
awk示例2
[root@oldxu ~]# cat b.txt
oldxu:is a:good boy!
[root@oldxu ~]# awk '{print NF}' b.txt
[root@oldxu ~]# awk -F ':' '{print NF}' b.txt
[root@oldxu ~]# awk -F"[ :]" '{print NF}' b.txt
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $1}' b.txt
oldxu
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $2}' b.txt
is
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $3}' b.txt
a
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $4}' b.txt
good
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $5}' b.txt
boy!
6.Awk条件判断
if语句格式: { if(表达式){语句;语句;... } }
1.以:为分隔符,打印当前管理员用户名称
awk 'BEGIN{FS=":"} { if($3==0) { print $1,"是管理员"} }' /etc/passwd
2.以:为分隔符,统计系统用户数量
awk 'BEGIN{FS=":"} { if($3<1000) { i++ }} END { print i,"系统用户" }' /etc/passwd
3.以:为分隔符,统计普通用户数量
awk 'BEGIN{FS=":"} { if ($3>=1000) { i++ } } END { print i,"个普通用 户"} /etc/passwd
4.以:为分隔符,只打印/etc/passwd中第3个字段的数值在50-100范围内的行信息
awk 'BEGIN{FS=":"} $3>=50 && $3<100 {print $0}' /etc/passwd
if…else 语句格式: {if(表达式){语句;语句;… }else{语句;语句;…}}
统计当前的超级管理员有几个 统计当前的普通用户有多少 统计当前的系统用户有多少个
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"} {if($3==0) {print $1} else {print $7}}' passwd
[root@oldxu ~]# awk 'BEGIN {FS=":"} {if($3==0) {count++} else{i++} }' /etc/passwd
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"} {if ($3==0) {count++} else {i++}} END {print "管理员个数:" count;print "系统用户数:"i}' passwd
管理员个数:1
系统用户数:38
if…else if…else 语句格式: { if(表达式 1){语句;语句;… }else if(表达式 2){语句;语句;. … }else{语句;语句;… }}
1.使用awk if打印出当前/etc/passwd文件管理员有多少个,系统用户有多少个,普通用户有多少个
[root@manager awk]# cat user_total.awk
BEGIN{
FS=":";OFS="\n"
}
{
if ($3==0)
{ i++ }
else if ($3>=1 && $3<=999)
{ j++ }
else
{ k++ }
}
END {
print i "个超级管理员",
j "个系统用户" ,
k "个普通用户"
}
1.打印/etc/passwd文件中UID小于50的、或者UID小雨50大于100、或者UID大于100的用户名以及UID。
UID<50 root 0
UID<50 bin 1
50100 systemd 192
UID>100 chrony 998
[root@chengyinwu /tmp/awk]# awk -f uid.awk passwd
[root@chengyinwu /tmp/awk]# cat uid.awk
BEGIN {
FS=":"
}
{
if ($3<50)
{
printf "%-20s%-20s%-10d\n","UID<50",$1,$3
}
else if ($3>50 && $3<100)
{
printf "%-20s%-20s%-10d\n","50100)
{
printf "%-20s%-20s%-10d\n","UID>100",$1,$3
}
}
2.计算下列每个同学的平均分数,并且只打印平均分数大于90的同学姓名和分数信息
[root@oldxu ~]# cat student.txt
oldxu 80 90 96 98
oldqiang 93 98 92 91
oldguo 78 76 87 92
oldli 86 89 68 92
oldgao 85 95 75 90
[root@chengyinwu /tmp/awk]# awk -f student.awk student.txt
[root@chengyinwu /tmp/awk]# cat student.awk
BEGIN{
printf "%-10s%-10s%-10s%-10s%-10s%-10s%-10s\n",
"Name","yuwen","shuxue","english","it","Total","AVG"
}
{
total=$2+$3+$4+$5
AVG=(total)/4
if ( AVG > 90) {
printf "%-10s%-10d%-10d%-10d%-10d%-10d%-10.2f\n",
$1,$2,$3,$4,$5,total,AVG
}
}
3.统计Nginx的状态,请分别打出200类 300类 400类 500类状态 出现了多少次
[root@manager awk]# awk -f log.awk access.log
[root@manager awk]# cat log.awk
BEGIN {
OFS="\n"
}
{
if($9>=200 && $9<300)
{i++}
else if ($9>=300 && $9<400) {
j++
}
else if ($9>=400 && $9<500) {
k++
}
else if ($9>=500 && $9<600) {
m++
}
}
END {
print "状态码: 次数",
"200类:"i"个",
"300类:"j"个",
"400类:"k"个",
"500类:"m"个" }
awk实战
1:若内存剩余小于200M则输出“NO”
[root@manager awk]# free -m |awk 'BEGIN{NR==2} $4<300{print "NO"}'
2:若硬盘剩余大于20G则输出“yes”
[root@manager awk]# df -h |awk 'NR==6 { if ($4 > 20) {print "yes"}}'
3:打印access.log中下载文件大小超过5M的行
5:打印当前系统中uid大于1000的用户
[root@manager awk]# awk 'BEGIN{FS=":"} $3>1000{print $1}' passwd
6:显示当前系统中容量使用率大于5%的文件系统名称和挂载点
[root@manager awk]# df -h |awk '{if($5>5){print $1,$NF}}'
cat /tmp/file1.txt
Mike Harrington:[510] 548-1278:250:100:175
Christian Dobbins:[408] 538-2358:155:90:201
Susan Dalsass:[206] 654-6279:250:60:50
Archie McNichol:[206] 548-1348:250:100:175
Jody Savage:[206] 548-1278:15:188:150
Guy Quigley:[916] 343-6410:250:100:175
Dan Savage:[406] 298-7744:450:300:275
Nancy McNeil:[206] 548-1278:250:80:75
John Goldenrod:[916] 348-4278:250:100:175
Chet Main:[510] 548-5258:50:95:135
Tom Savage:[408] 926-3456:250:168:200
Elizabeth Stachelin:[916] 440-1763:175:75:300
7:显示/tmp/file1.txt文件中所有电话号码
[root@manager awk]# awk 'BEGIN{FS="[: ]"} {print $4}' file1.txt
8:显示/tmp/file1.txt文件中Dan的电话号码
方法一:[root@manager awk]# awk -F "[: ]" '/Dan/ {print $4}' file1.txt
方法二:[root@manager awk]# awk 'BEGIN{FS="[: ]"}/Dan/{print $4}' file1.txt
9:显示/tmp/file1.txt文件中Susan的名字和电话号码
[root@manager awk]# awk -F "[ :]" '/Susan/ {print $1,$2,$4}' file1.txt
10:显示/tmp/file1.txt文件中所有区号为916的人名
[root@manager awk]# awk 'BEGIN{FS="[ :]"} /\[916\]/ {print $1,$2}' file1.txt
11:显示/tmp/file1.txt文件中所有头一个月捐款$250的人名
[root@manager awk]# awk 'BEGIN{FS="[ :]"} $5 ~ /250/ {print $1,$2}' file1.txt
12:显示/tmp/file1.txt文件中Savage的全名和电话号码
[root@manager awk]# awk 'BEGIN{FS="[ :]"} /Savage/ {print $1,$2,$4}' file1.txt
13:显示/tmp/file1.txt文件中只有四个字符的名
[root@manager awk]# awk '$1 ~/^[a-zA-Z]{4}$/' file1.txt
14:以空格文分隔符将/tmp/file1.txt文件中的第一列与最后一列调换位置
[root@manager awk]# awk 'BEGIN{FS=" "}{print $NF,$1}' file1.txt
15:使用awk取出IP地址
[root@manager awk]# ifconfig eth0 |awk 'NR==2{print $2}'
16:使用awk取出/etc/passwd第一列数据也就是取出用户名。
[root@manager awk]# awk 'BEGIN{FS=":"}{print $1}' passwd