1.awk
1.1执行流程
1.2print
print item1,item2,…
要点:
(1)逗号分隔符
(2)输出的item可以是字符串,也可以是数值,当前记录的字段,变量或awk的表达式
(3)如省略item,相当于print $0
1.3变量
内建变量
FS:input field seperator,输入间隔符,默认为空白字符
OFS:output field separator,输出间隔符,默认为空白字符
RS:input record separator,输入时的换行符
ORS:output record separator,输出时的换行符
NF:number of field,字段数量,{print NF} 输出字段的数量{print $NF}输出最后一列
NR:number of record,行数
FNR:各文件分别计数,行数
FILENAME:当前文件名
ARGC:命令行参数个数
ARGV:数组,保存的是命令行所给定的各个参数
自定义变量
方式一:
-v var=value 变量名区分字符大小写
方式二:
在program中直接定义
下面这两个最重要:
NF:number of field,字段数量,{print NF} 输出字段的数量{print $NF}输出最后一列
NR:number of record,行数
[root@m01 oldboy]# awk -v FS=":" '{print $1}' /etc/passwd
root
bin
daemon
adm
lp
syn
分隔符为一个或多个:,打印第一列,第三列内容
默认输出分隔符为空格
[root@m01 oldboy]# awk -F '[:]+' '{print $1,$3}' /etc/passwd
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
设置输出分隔符
[root@m01 oldboy]# awk -F '[:]' -v OFS=':' '{print $1,$3}' /etc/passwd
root:0
bin:1
daemon:2
adm:3
打印每行的列数
[root@m01 oldboy]# awk -F '[:]' '{print NF}' /etc/passwd
7
7
7
7
1.4printf命令
格式化输出:printf FORMAT,item1,item2,…
(1)FORMAT必须给出
(2)不会自动换行,需要显示给出换行控制符,\n
(3)FORMAT中需要分别为后面的每个Item指定一个格式化符号
格式符:
%c:显示字符的ASCII码
%d,%i:显示十进制整数
%e,%E:科学技术法数值显示
%f:显示为浮点数
%g,%G以科学技术法祸福点形式显示数值
%s:显示字符串
%u:无符号整数
%%:显示%本身
修饰符:
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度
%3.1f
-:左对齐
+:显示数值的符号
实践操作
[root@m01 oldboy]# awk -F "[:]" '{printf "Username:%s,UID:%d\n",$1,$3}' /etc/passwd
Username:root,UID:0
Username:bin,UID:1
Username:daemon,UID:2
右对齐,%15s意思是占据15个字符长度,右对齐
[root@m01 oldboy]# awk -F "[:]" '{printf "Username:%15s,UID:%d\n",$1,$3}' /etc/passwd
Username: root,UID:0
Username: bin,UID:1
Username: daemon,UID:2
Username: adm,UID:3
左对齐
[root@m01 oldboy]# awk -F "[:]" '{printf "Username:%-15s,UID:%d\n",$1,$3}' /etc/passwd
Username:root ,UID:0
Username:bin ,UID:1
Username:daemon ,UID:2
Username:adm ,UID:3
[root@m01 oldboy]# awk -F: '{$3>1000?usertype="Common user":usertype="Sysadmin user";printf "%15s:%s\n",$1,usertype}' /etc/passwd
root:Sysadmin user
bin:Sysadmin user
daemon:Sysadmin user
adm:Sysadmin user
lp:Sysadmin user
-F设置多个分隔符
[root@m01 oldboy]# cat /etc/fstab|grep -Ev '^#'|awk -F '[: ]+' '{print $0}'
UUID=b3a88d2b-b491-46ff-96a1-a9eff1a5c3a5 / ext4 defaults 1 1
UUID=8848e519-989b-4a1f-9fdb-803f0b56db57 /boot ext4 defaults 1 2
UUID=b6a11888-75c1-4a5f-98fa-32c323404e4e swap swap defaults 0 0
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
[root@m01 oldboy]# cat /etc/fstab|grep -Ev '^#'|awk -F '[: ]+' '{print $2}'
/
/boot
swap
/dev/shm
/dev/pts
/sys
/proc
[root@m01 oldboy]#
1.5操作符
算数操作符:
x+y, x-y, x*y, x/y, x^y, x%y
-x
+x:转换为数值
字符串操作符:没有符号的操作符,字符串连接
赋值操作符:
=, +=, -=, *=, /=, %=, ^=, ++, --
比较操作符:
>,>=, <, <=, !=, ==
格式匹配符:
~:是否匹配
!~:是否不匹配
逻辑操作符:
&&, ||, !
函数调用:
function_name(argu1,argu2,…)
条件表达式:
selector?if-true-express:if-false-express
实践操作:
[root@m01 oldboy]# awk '/^UUID/{print $1}' /etc/fstab
UUID=b3a88d2b-b491-46ff-96a1-a9eff1a5c3a5
UUID=8848e519-989b-4a1f-9fdb-803f0b56db57
UUID=b6a11888-75c1-4a5f-98fa-32c323404e4e
!取反
[root@m01 oldboy]# awk '!/^UUID/{print $1}' /etc/fstab
#
#
#
#
#
#
#
tmpfs
devpts
sysfs
proc
[root@m01 oldboy]#
[root@m01 oldboy]# awk -F: -v OFS=":" '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
root:/bin/bash
oldboy:/bin/bash
stu01:/bin/bash
stu02:/bin/bash
~模式匹配
[root@m01 oldboy]# awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd
root /bin/bash
oldboy /bin/bash
stu01 /bin/bash
1.6PATTERN
(1)empty:空模式,匹配每一行
(2)/regular express/:仅处理能够被此处模式匹配的行
(3)relational express:关系表达式:结果有“真”有”假”,结果为” 真”才会被处理
(4)line ranges:行范围,startline,endline: /pat1/,/pat2/
注意:不支持直接给出数字的格式
(5)BEGIN/END模式
BEGIN{}:仅在开始处理文件中的文本之前执行一次;
END{}:仅在文本处理完成之后执行一次
实践操作
[root@m01 oldboy]# awk '{if (NR>2&&NR<5) print $0}' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
关系表达式
[root@m01 oldboy]# awk '{(NR>2&&NR<5) print $0}' /etc/passwd
awk: {(NR>2&&NR<5) print $0}
awk: ^ syntax error
[root@m01 oldboy]# awk '(NR>2&&NR<5){print $0}' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@m01 oldboy]# df -h|awk -F '[%]' '/^\/dev/{print $1}'
/dev/sda3 8.8G 7.0G 1.4G 84
/dev/sda1 190M 40M 141M 22
/dev/sdb1 20G 1.2G 18G 7
[root@m01 oldboy]# df -h|awk -F '[%]' '/^\/dev/{print $0}'|awk '{if (NR>1) print $0}'
/dev/sda1 190M 40M 141M 22% /boot
/dev/sdb1 20G 1.2G 18G 7% /project
起始行和结束行
[root@m01 oldboy]# awk -F: '/^root/,/^test/{print $1}' /etc/passwd
root
bin
daemon
adm
lp
test
BEGIN,END只打印一次,中间的内容,是匹配多少行就打印多少次
[root@m01 oldboy]# awk -F: 'BEGIN{print "user-----------"}{if (NR>2&&NR<5) print $0}END{print "end----------"}' /etc/passwd
user-----------
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
end----------
1.7常用的action
(1)Expressions
(2)Control statements:if while等
(3)Command statements:组合语句
(4)input statements
(5)output statements
1.8控制语句
if(condition) {statements}
if(condition) {statements} else {statements}
while(condition) {statements}
do {statements} while(condition)
for(expr1;expr2;expr3) {statements}
break
continue
delete array[index]
delete array
exit
{statements}
if-else
语法:if(condition) {statements} else {statements}
使用场景:对awk取得的整行或某个字段做条件判断
common user: vita
[root@m01 oldboy]# awk -F: '{if($3>1000){printf "common user:%15s\n",$1}else{printf "sysadmin user:%15s\n",$1}}' /etc/passwd
common user: oldboy16
common user: oldboy17
common user: www
sysadmin user: redis
sysadmin user: rabbitmq
[root@m01 oldboy]# awk '{if(NR==3)print $0}' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@m01 oldboy]# awk '{if($NF=="/bin/bash")print $0}' /etc/passwd
[root@m01 oldboy]# awk -F: '{if($NF=="/bin/bash")print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
oldboy:x:1000:1000::/home/oldboy:/bin/bash
stu01:x:1013:1013::/home/stu01:/bin/bash
while循环
语法:while(condition) statements
条件“真”,进入循环,条件“假”,退出循环
使用场景:对一行内的多个字段逐一类似处理时使用:对数组中的各元素逐一处理时使用
[root@m01 oldboy]# awk '/^UUID/{i=1;while (i<NF){print $i;i++}}' /etc/fstab
UUID=b3a88d2b-b491-46ff-96a1-a9eff1a5c3a5
/
ext4
defaults
1
UUID=8848e519-989b-4a1f-9fdb-803f0b56db57
/boot
ext4
defaults
1
UUID=b6a11888-75c1-4a5f-98fa-32c323404e4e
swap
swap
defaults
0
do-while循环
语法:do {statements} while(condition) 意义:至少执行一次循环体
for循环
语法:for(expr1;expr2;expr3) {statements}
特殊用法:能够遍历数组中的元素
语法:for(var in array) {statements}
[root@m01 oldboy]# awk '/^UUID/{for (i=1;i<NF;i++)print $i}' /etc/fstab
UUID=b3a88d2b-b491-46ff-96a1-a9eff1a5c3a5
/
ext4
defaults
1
UUID=8848e519-989b-4a1f-9fdb-803f0b56db57
/boot
ext4
defaults
1
UUID=b6a11888-75c1-4a5f-98fa-32c323404e4e
swap
swap
defaults
0
[root@m01 oldboy]
switch语句
语法:switch(expression) {case VALUE1 or /REGEXP/:statement; case VALUE2 or /REGEXP2/:statement;…;default:statement}
break和continue
break [n] continue
next
提前结束对本行的处理而直接进入下一行
1.9array数组(shell脚本中有案例)
通过awk同时分析出secure文件中每个用户被每个ip破解的次数通过awk同时分析access.log文件每个ip的重复数和每个ip使用的流量
[root@oldboyedu-01 ~]# cat /oldboy/access.log |awk '{array[$1]++;sum[$1]=sum[$1]+$10}END{for (ip in array) print ip,array[ip],sum[ip]}'
180.97.106.162 2 336
180.97.106.37 4 672
通过awk同时分析出secure文件中每个用户被每个ip破解的次数
[root@oldboyedu-01 ~]# cat /oldboy/secure.txt |grep 'Failed'|awk '{array[$9,$11]++}END{for (i in array) print i,array[i]}'
oldboy10.0.0.1 2
oldboy10.0.0.3 1
root10.0.0.1 5
root10.0.0.2 3
1.10函数
函数
内置函数
数值处理:
rand():返回0和1之间一个随机数
字符串处理:
length([s]):返回指定字符串的长度
sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容
gsub:以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现替换为s所表示的内容
split(s,a[],r):以r为分隔符切割字符s,并将其切割后的结果保存至a所表示的数组中
自定义函数