awk 语法结构
awk [options] 'commands' file(s)
option:
-F 定义字段分割符号
-v 定义变量并赋值
command:
1、范围说明或者正则表达式或者{awk命令语句1;awk命令语句2;}
2、范围说明部分可以是BEGIN、END、逻辑表达式或者为空
3、awk命令语句间用分号间隔
4、引用shell变量时需要用双引号引起,命令模式都在单引号''里面
BEGIN{} {} END{}
行处理前 行处理 行处理后
字段分割及相关变量
$1,$2,$3...$n:awk中用该顺序形式表示files中每行以间隔符号分割的各列的不同字段
$0 表示文本本身
NF 表示当前记录的字段数(列数)
$NF 最后一列
$(NF-1) 倒数第二列
FNR/NR 行号
FILENAME 文件名
"\t" 制表符
RS/ORS 换行符
"" 打印字符串
FS/OFS 定义间隔符
~ 匹配,与==相比不是精确比较
!~ 不匹配,不精确比较
== 等于,必须全部相等,精确比较
/[0-9][0-9]+/ 两个或两个以上数字
-F'[:#/]' 定义三个分隔符
常用内置变量举例
awk -F: '{print $0}' /etc/passwd #打印文件所有内容
awk -F: '{print NR, $0}' /etc/passwd /etc/hosts #打印文件所有内容,并包括行号
awk -F: '{print FNR,$0}' /etc/passwd /etc/hosts
awk -F: '{print $0,NF}' /etc/passwd #保留记录的字段数
awk 'BEGIN{FS=":"}{print $1,$3}' /etc/passwd #输入字段分隔符,默认为空格
分隔符
[root@linux /]# echo "aa bb cc"|awk '{print $2}' #分隔空格
bb
[root@linux /]# echo "aa bb cc"|awk -F " " '{print $2}' #分隔空格
bb
[root@linux /]# awk -F: '{print $1}' /etc/passwd|wc -l #统计系统用户数
33
指定多个分隔符
[root@linux /]# echo "11 22 33:44:55"|awk -F"[ :]" '{print $2}'
22
[root@linux /]# echo "11-22-33:44:55"|awk -F"[-:]" '{print $3}'
33
使用FS和OFS指定分隔符
[root@linux /]# echo "aaa222bbb"|awk 'BEGIN{FS="222";OFS=":"}{print $2}'
bbb
[root@linux /]# head -1 /etc/passwd >passwd
[root@linux /]# awk -F: 'BEGIN{OFS="-"}{print $1,$2,$3}' passwd
root-x-0
换行符
[root@linux /]# cat xxx.txt
127.0.0.1
[root@linux /]# awk 'BEGIN{RS="."}{print $0}' xxx.txt
127
0
0
1
[root@linux /]# cat xxx.txt
127.0.0.1
hello
world
[root@linux /]# awk 'BEGIN{ORS=" "}{print $0}' xxx.txt #将多行内容合并成一行
127.0.0.1 hello world
格式化输出
print函数
[root@linux /]# date|awk '{print "Year:" $NF "\nMonth:" $2 "\nDay:" $3}' #显示年月日
Year:2020
Month:Aug
Day:15
[root@linux /]# awk 'BEGIN{OFS="-";print "Hello","world"}'
Hello-world
[root@linux /]# awk -F: '{print "User:" $1 "\t Shell:" $NF}' /etc/passwd
[root@linux /]# awk -F: '{print "\User: " $1,$NF}' /etc/passwd
printf函数
awk -F: '{printf "%-15s %-10s %-15s\n", $1,$2,$3}' /etc/passwd
awk -F: '{printf "|%15s| %10s| %15s|\n", $1,$2,$3}' /etc/passwd
awk -F: '{printf "|%-15s| %-10s| %-15s|\n", $1,$2,$3}' /etc/passwd
参数解释:
%s 字符类型 strings %-20s
%d 数值类型
占15字符
- 表示左对齐,默认是右对齐
printf默认不会在行尾自动换行,加\n
awk的模式和动作
awk变量定义
[root@linux /]# awk -v us=2 'BEGIN{print us}'
2
[root@linux /]# awk -v us=1 -F: 'NR==1{print $us}' /etc/passwd
root
正则表达式
awk '/^root/' /etc/passwd #匹配root开头的行
awk '!/^root/' /etc/passwd #匹配除了root开头的行
模式匹配表达式
awk -F: '$1 ~ /^admin/' /etc/passwd
awk -F: '$NF !~ /nologin/' /etc/passwd
比较表达式
比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。比较表达式使用关系运算符,用于比较数字与字符串
运算符 含义
< 小于
<= 小于或等于
== 等于
!= 不等于
>= 大于等于
> 大于
[root@linux /]# awk -F: '$1 == "root" ' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@linux /]# awk -F: '$NF == "/bin/bash" ' /etc/passwd
root:x:0:0:root:/root:/bin/bash
admin:x:1000:1000::/home/admin:/bin/bash
[root@linux /]# awk -F: '$3 < 10 ' /etc/passwd
运算符
+ - * / 加减乘除
[root@linux /]# cat xxx.txt
10 2
[root@linux /]# awk '{print $1 / $2}' xxx.txt #除
5
[root@linux /]# awk '{print $1 * $2}' xxx.txt #乘
20
[root@linux /]# awk '{print $1 - $2}' xxx.txt #减
8
逻辑运算符
&& 逻辑与 a&&b
|| 逻辑或 a||b
! 逻辑非 !a
[root@linux /]# awk -F: '$3==0 && $NF=="/bin/bash" {print $1 "\t" $NF}' /etc/passwd
root /bin/bash
[root@linux /]# awk -F: '$3==0||$NF=="/bin/bash" {print $1 "\t" $NF}' /etc/passwd
root /bin/bash
admin /bin/bash
[root@linux /]# awk -F: '!($3 == 0 || $3 <=10)' /etc/passwd
awk脚本模式
条件判断
if语句
{if(表达式){语句;语句;...}}
[root@linux /]# awk -F: '{if($3==0){print $1 "\tadmiinistrator"}}' /etc/passwd
root admiinistrator
[root@linux /]# awk -F: '{if($1){count++}} END{print count}' /etc/passwd #统计系统用户数
45
[root@linux /]# awk 'BEGIN{if('$(id -u)'==0) {print "administrator"} }'
administrator
if...else语句
格式:
{if(表达式){语句;语句;...}else{语句;语句;...}}
[root@linux /]# awk -F: '{if($3==0){print $1"\t这是管理员"}else{print $1"\t这是普通用户"}}' /etc/passwd
[root@linux /]# awk -F: '{if($3==0){x++} else{i++}} END{print "管理员个数: "x ; print "系统用户数: "i}' /etc/passwd
管理员个数: 1
系统用户数: 32
if...else if...else语句
{if(表达式1){语句;语句;...}else if(表达式2){语句;语句;...}else if(表达式3){语句;语句;...}else{语句;语句;...}}
awk -F: '{if($3==0){print "我是管理员用户"$1}else if($3<999){print "我是系统用户"$1}else if($3>1000){print "我是普通用户"$1}}' /etc/passwd
循环
while循环
awk 'BEGIN{i=1; while(i<=10){print i; i++}}'
awk 'BEGIN{ip="192.168.1."; i=1; while(i<255){print ip i;i++}}'
for循环
awk 'BEGIN{for(i=0;i<5;i++){print i}}'
awk 'BEGIN{for(i=1;i<=5;i+=2){print i}}'
awk -F: '{for(i=1;i<=10;i++) print $0}' /etc/passwd
数组
[root@linux /]# awk -F: '{user[i++]=$1}END{print user[0]}' /etc/passwd
root
[root@linux /]# awk -F: '{user[i++]=$1}END{print user[1]}' /etc/passwd
bin
[root@linux /]# awk -F: '{user[i++]=$1}END{print user[2]}' /etc/passwd
daemon
[root@linux /]# cat /etc/passwd|head -3
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
数组遍历
统计Shell
[root@linux /]# awk -F: '{shell[$NF]++}END{for(i in shell){print i,shell[i]}}' /etc/passwd
/bin/sync 1
/bin/bash 2
/sbin/nologin 25
/sbin/halt 1
/sbin/shutdown 1
统计登录SSH失败的用户
[root@linux /]# lastb|awk '{name[$1]++}END{for(i in name){print i,name[i]}}'|sort -k2rn|head -3
root 393
ubuntu 92
test 90
统计网站访问状态
[root@linux /]# ss -an|grep :80|awk '{x[$2]++}END{for(i in x){print i,x[i]}}'|sort -k2rn
ESTAB 24
TIME-WAIT 3
LISTEN 1