Linux Awk
Written on October 9th, 2017 by Dzreal
awk 用法
简介:awk 主要用于统计和查看文本
语法
awk [options] ‘command’ file
常用参数(options)
- -f 调用脚本
- -F 指定‘分隔符’,指定多个分隔符(指定:和#作为分隔符): -F ‘[:#]’
- -v 定义变量
常用特殊变量
- $0 表示整个当前行
- $1 每行第一个字段
- NF 字段数量变量
- NR 行号
- FILENAME 文件名
- OFS 制表符
特殊要点
- ~ 匹配
- !~ 不匹配
- == 等于,必须全等,精确比较
- != 不等于,精确比较
- && 逻辑与
- 两根竖线(坑爹的markdown语法打不出来) 逻辑或
常用命令:
- print 打印字符
- 条件判断语句
- if(表达式){语句}else if(表达式){语句}else(表达式)(语句)
- 循环语句
- while(表达式){语句}
- for(变量 in 数组){语句}
- for(变量;条件;表达式){语句}
- do{语句}while(条件)
程序结构
- BEGIN 初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符
- // 匹配代码块,可以是字符串或正则表达式
- {} 命令代码块,包含一条或多条命令
- ; 多条命令使用分号分隔
- END 结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息
用法:awk -F ‘分隔符’ ‘BEGIN{程序开始时要做的命令}/pattern/{逐行匹配的时候要做的命令}END{程序执行完毕需要做的命令}’ file
例子
# 以 /etc/passwd 文件为例:
# passwd 文件说明:
# 用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录Shell
# (1)查看/etc/passwd下的用户名和口令,并添加前缀
awk -F ':' '{print "user:"$1 "\t" "passwd:"$2}' /etc/passwd
# 输出:
# user:root passwd:x
# user:daemon passwd:x
# user:bin passwd:x
# user:sys passwd:x
# ...
# (2)查看/etc/passwd下的用户名和口令,并添加表头
awk -F ':' 'BEGIN{print "user""\t""passwd"}{print $1 "\t" $2}END{print "---filename:---"FILENAME}' /etc/passwd
# 输出:
# user passwd
# root x
# daemon x
# bin x
# sys x
# sync x
# ...
# ---filename:---/etc/passwd
# (3)查看/etc/passwd下的用户名和口令,并在每行开头打印出行号
awk -F ':' '{print NR " " "user:"$1 " " "passwd:"$2}' /etc/passwd
# 输出:
# 1 user:root passwd:x
# 2 user:daemon passwd:x
# 3 user:bin passwd:x
# 4 user:sys passwd:x
# 5 user:sync passwd:x
# 6 user:games passwd:x
# ...
# (4)统计/etc/passwd文件的行数和字段数
awk -F ':' 'END{print "行数:"NR "\t" "字段数:"NF}' /etc/passwd
# 输出:
# 行数:37 字段数:7
# (5)统计"bin"在/etc/passwd出现次数
awk -F ':' 'BEGIN{count=0}/bin/{count++}END{print "bin出现次数:"count}' /etc/passwd
# 输出:
# bin出现次数:36
# (6)自定义变量的使用案例
awk -v dzreal=DZREAL -F ':' 'BEGIN{print "user" "\t" "operator"}{print $1 "\t" dzreal}' /etc/passwd
# 输出:
# user operator
# root DZREAL
# daemon DZREAL
# bin DZREAL
# sys DZREAL
# sync DZREAL
# ...
# (7)显示第5行和第6行
awk -F: 'NR==5 || NR==6{print}' /etc/passwd
# 输出:
# sync:x:4:65534:sync:/bin:/bin/sync
# games:x:5:60:games:/usr/games:/usr/sbin/nologin
# (8)$1匹配指定内容才显示
awk -F: '$1~/mail/{print $0}' /etc/passwd
# 输出:
# mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
# (9)显示$1不匹配的部分
awk -F: '$1!~/mail/{print $1}' /etc/passwd
# 输出:
# root
# daemon
# bin
# sys
# sync
# ...
# (10)输出前5个字段并使用"|"分隔
awk -F: '{print $1,$2,$3,$4,$5}' OFS='|' /etc/passwd
# 输出:
# root|x|0|0|root
# daemon|x|1|1|daemon
# bin|x|2|2|bin
# sys|x|3|3|sys
# ...
# (11)计算当前目录下,普通文件的大小,使用KB作为单位,int是取整的意思
ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is:",int(sum/1024),"KB"}'
# 输出:
# total size is: 9908 KB
# (12)统计netstat -anp 状态为LISTEN和CONNECT的连接数量分别是多少
netstat -anp|awk '$6~/LISTEN|CONNECTED/{sum[$6]++} END{for (i in sum){print i," ",sum[i]}}'
# 或
netstat -anp|awk '$6~/LISTEN|CONNECTED/{sum[$6]++} END{for (i in sum){printf "%-10s %-6s %-3s \n", i," ",sum[i]}}'
# 输出:
# LISTEN 11
# CONNECTED 48
# 解释:
# printf表示格式输出
# %格式化输出分隔符
# -8长度为8个字符
# s表示字符串类型
# 打印每行前三个字段,指定第一个字段输出字符串类型(长度为10),第二个字段输出字符串类型(长度为6),第三个字段输出字符串类型(长度为3),
#(13)统计当前目录下不同用户的普通文件的总数是多少?
ls -al|awk 'NR!=1 && !/^d/{sum[$3]++} END{for (i in sum) printf "%-6s %-5s %-3s \n",i," ",sum[i]}'
# 输出:
# root 3
#(14)统计Nginx的access.log,统计url以及url出现的次数
tail -1000 access.log | awk -F ' ' '!/"-"/{sum[$11]++}END{for(i in sum){print "url:"i,"count:"sum[i]}}' OFS="\t"
# 输出:
# url:"http://123.205.30.222//wuwu11.php" count:2
# url:"http://123.205.30.222//hm.php" count:1
# url:"http://123.205.30.222" count:1
# url:"http://123.205.30.222:80/invoker/readonly" count:1
# url:"http://123.205.30.222/l.php" count:7
# url:"http://123.205.30.222//xx.php" count:2
Feel free to share!