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
Last modification:September 10th, 2020 at 02:32 am
如果觉得我的文章对你有用,请随意赞赏