一、awk介绍
awk是一种优良的文本处理工具
awk提供了极其强大的功能,可以进行样式装入,流控制,数学运算符,进程控制语句,甚至于内置的变量和函数,主要用于数据扫描、过滤、统计汇总工作
awk工具可以扫描文件中的每一行,查找与命令行中所给定内容相匹配的模式
我们常使用sed和awk相结合的方式处理,使文本处理命令更快捷
二、awk语法
awk 选项 命令 文件
awk [-F | -f | -v ] ‘BEGIN {} / /{command1;command2} END {}’file
‘{}’ 引用代码块
{…} 命令代码块,包含一条或多条命令
BEGIN 初始化代码块
/ str / 匹配代码块,可以是字符串或正则表达式
{print A;printB} 多条命令使用分号分隔
END 结尾代码块
awk选项:
-F:定义字段分隔符,默认的分隔符是连续的空格,可以通过此选项任意指定
awk '{print $1}' a.txt
awk -F: '{print $1,$2}' a.txt (以:为分隔符)
-v:参数传递,定义和引用变量,可以把外部变量引入到内部
- 用-v指定 var=value 变量名区分大小写的
- 在程序中直接定义
- 在awk里,使用变量不用加$符号
- num1=10
- var="hello word"
awk -v num1=$num2 -v var1="$var" `BEGIN{print num1,var1}`-f:指定脚本
vim test.awk
#! /bin/bash
BEGIN{print num2,var1}
awk -v num2=$num1 -v var1=$var -f test.awk
-V:查看awk的版本号
awk命令:
读前处理BEGIN{awk_cmd1;awk_cmd2}:
awk 'BEGIN {print "hello,World"}'
行处理:定址命令(正则表达式需要用/ /包围起来)
awk -F: '/root/{print}' /etc/passwd
awk -F: '$1~/root/{print}' /etc/passwd
awk -F: '$1!~/root/{print}' /etc/passwd
读后处理END {awk_cmd1;awk_cmd2;}
awk -F: 'BEGIN{i=1} {i++} END {print i}' /etc/passwd
BEGIN可以进行数据初始化,END可以进行数据汇总
awk内置变量(预定义变量):
- $n 当前记录的第n个字段,比如: $1表示第一个字段,$2表示第二个字段
- $0 这个变量包含执行过程中当前行的文本内容
- FILENAME 当前输入文件的名
- FS 字段分隔符(默认是空格)
- NF 表示字段数,在执行过程中对应于当前的字段数,NF:列的个数
- FNR 各文件分别计数的行号
- NR 表示记录数,在执行过程中对应于当前的行号
- OFS 输出字段分隔符(默认值是一个空格)
- ORS 输出记录分隔符(默认值是一个换行符)
- RS 记录分隔符(默认是一个换行符)
- ARGC 命令行参数个数
- ARGV 命令行参数排列
- ENVIRON 输出系统环境变量
- \t 制表符
- \n 换行符
- ~ 匹配
- !~ 不匹配
- -F'[:#/]+' 定义三个分隔符
- \\ \自身
- \$ 转义$
- \b 退格符
- \r 回车符
- \c 取消换行
awk内置函数 :
算数函数:sqrt(求平方根)、
rand(当参数缺省的时候,使用当前时间作为随机数种子)、
srand(内置函数rand的伪随机函数,其返回值范围在【0,1】,实际使用时,一般使用srand生成随机数种子,在使用rand函数生成随机数,否则每次的值都一样)。
[root@manager ~]# awk 'BEGIN{x=sqrt(100);print x}'
10
[root@manager ~]# awk 'BEGIN{x=rand();print x}'
0.237788
[root@manager ~]# awk 'BEGIN{srand();x=int(100*rand());print x}'
64
字符串函数:sub和gsub函数(替换符,前者是只替换第一个,后者是替换所有)、
index函数(查找字符)
length函数(计算长度)
substr函数(截取字符串)
match函数(正则匹配查找)
split函数(字符分割)
[root@manager ~]# awk 'BEGIN{info="this is a
test2010test2010test!";sub(2010,"!",info);print info}'
this is a test!test2010test!
[root@manager ~]# awk 'BEGIN{info="this is a
test2010test2010test!";gsub(2010,"!",info);print info}'
this is a test!test!test!
[root@manager ~]# awk 'BEGIN{info="this is test2010test!";print
index(info,"test")?"ok":"not found";}'
ok
[root@manager ~]# awk 'BEGIN{info="hello";print length(info)}'
5
[root@manager ~]# awk 'BEGIN{info="hello world";print substr(info,4,10)}'
lo world
[root@manager ~]# awk 'BEGIN{info="hello 2016world";print match(info,/[0-
9]+/)?"ok":"none";}'
ok
[root@manager ~]# awk 'BEGIN{info="hello world";split(info,test);print length(test);for(k
in test){print k,test[k];}}'
2
1 hello
2 world
一般函数:
close( Expression )
用同一个带字符串值的 Expression 参数来关闭由 print 或 printf 语句打开的或调用 getline 函数打开的文件或管道。如果文件或管道成功关闭,则返回 0;其它情况下返回非零值。如果打算写一个文件,并稍后在同一个程序中读取文件,则 close 语句是必需的。
system(Command )
执行 Command 参数指定的命令,并返回退出状态。等同于 system 子例程。
Expression | getline [ Variable ]
从来自 Expression 参数指定的命令的输出中通过管道传送的流中读取一个输入记录,并将该记录的值指定给 Variable 参数指定的变量。如果当前未打开将 Expression 参数的值作为其命令名称的流,则创建流。创建的流等同于调用 popen 子例程,此时 Command 参数取 Expression 参数的值且 Mode 参数设置为一个是 r 的值。只要流保留打开且 Expression 参数求得同一个字符串,则对 getline 函数的每次后续调用读取另一个记录。如果未指定 Variable 参数,则 $0 记录变量和 NF 特殊变量设置为从流读取的记录。
getline [ Variable ] < Expression
从 Expression 参数指定的文件读取输入的下一个记录,并将 Variable 参数指定的变量设置为该记录的值。只要流保留打开且 Expression 参数对同一个字符串求值,则对 getline 函数的每次后续调用读取另一个记录。如果未指定 Variable 参数,则 $0 记录变量和 NF 特殊变量设置为从流读取的记录。
getline [ Variable ]
将 Variable 参数指定的变量设置为从当前输入文件读取的下一个输入记录。如果未指定 Variable 参数,则 $0 记录变量设置为该记录的值,还将设置 NF、NR 和 FNR 特殊变量。
[root@manager ~]# awk 'BEGIN{while("head -5 /etc/passwd"|getline){print $0;};close("/etc/passwd");}'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@manager ~]# awk 'BEGIN{while(getline < "/etc/passwd"){print $0;};close("/etc/passwd");}'
[root@manager ~]# awk 'BEGIN{print "Enter your name:";getline name;print name;}'
Enter your name:
robin
robin
[root@manager ~]# awk 'BEGIN{b=system("ls -l /root");print b;}'
总用量 20
-rw-r--r-- 1 root root 135 9月 18 16:14 aa.txt
-rw-------. 1 root root 905 9月 9 06:30 anaconda-ks.cfg
-rw-r--r--. 1 root root 8003 9月 9 06:30 install.log
-rw-r--r--. 1 root root 3384 9月 9 06:30 install.log.syslog
0
[root@manager test7]# awk -F: 'BEGIN{x=system("id robin &>/dev/null");if(x==0){while(getline < "/etc/passwd")if($1=="robin")print $1,$6}}'
robin /home/robin
时间函数:
函数名
说明
mktime( YYYY MM DD HH MM SS[ DST])
生成时间格式
strftime([format [, timestamp]])
格式化时间输出,将时间戳转为时间字符串 具体格式,见下表.
systime()
得到时间戳,返回从1970年1月1日开始到当前时间(不计闰年)的整秒数
[root@manager ~]# awk 'BEGIN{tstamp=mktime("2001 01 01 12 12 12");print strftime("%c",tstamp);}'
2001年01月01日 星期一 12时12分12秒
[root@manager ~]# awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=mktime("2001 02 01 0 0 0");print tstamp2-tstamp1;}'
2634468
[root@manager ~]# awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=systime();print tstamp2-tstamp1;}'
495876393
strftime日期和时间格式说明符:
格式
描述
%a
星期几的缩写(Sun)
%A
星期几的完整写法(Sunday)
%b
月名的缩写(Oct)
%B
月名的完整写法(October)
%c
本地日期和时间
%d
十进制日期
%D
日期 08/20/99
%e
日期,如果只有一位会补上一个空格
%H
用十进制表示24小时格式的小时
%I
用十进制表示12小时格式的小时
%j
从1月1日起一年中的第几天
%m
十进制表示的月份
%M
十进制表示的分钟
%p
12小时表示法(AM/PM)
%S
十进制表示的秒
%U
十进制表示的一年中的第几个星期(星期天作为一个星期的开始)
%w
十进制表示的星期几(星期天是0)
%W
十进制表示的一年中的第几个星期(星期一作为一个星期的开始)
%x
重新设置本地日期(08/20/99)
%X
重新设置本地时间(12:00:00)
%y
两位数字表示的年(99)
%Y
当前月份
%Z
时区(PDT)
%%
百分号(%)
printf函数:是格式化输出函数,一般用于向标准输出设备按规定格式输出信息
printf()函数的调用格式为:
%d 十进制有符号整数
%u 十进制无符号整数
%f 浮点数
%s 字符串
%c 单个字符
%p 指针的值
%e 指数形式的浮点数
%x, %X 无符号以十六进制表示的整数
%o 无符号以八进制表示的整数
%g 自动选择合适的表示法
\n 换行
\f 清屏并换页
\r 回车
\t Tab符
\xhh 表示一个ASCII码用16进表示,其中hh是1到2个16进制数
输出样式 %s是字符类型,%d数值类型
printf默认是不输出换行的所以要加\n
10和7是偏移量 默认是右对齐,所有加个- 就是左对齐,就是把不足的位数用空格填充
注意:格式与输出列之间要有逗号
[root@manager ~]# awk 'BEGIN{a=16;printf "%-10o\n",a}'
20
常用命令
cat example.txt | awk 'NR%2==1' #删除example.txt文件中的所有偶数行
echo " false" |awk -F' ' '{print $NF}' #去掉前面的空格
docker images | grep 'mysql' | awk '{printf"%s:%s\n",$1,$2}' #获取镜像名:Tag
ps -ef | grep java | grep -v 'color' awk '{for (i=8;i<=NF;i++)printf("%s ", $i);print ""}' #获取从第八列开始到最后一列的内容
1
2
3
4
常用技巧
打印各磁盘可用大小
df | grep -v tmpfs | awk 'NR!=1 {disk[$1]=$4} \
END {for(i in disk) {printf "%-20s %-10s\n",i,disk[i]/1024"M"}
}'
1
2
3
统计磁盘可用容量
df | tail -n +2 | grep -v tmpfs | awk '{sum+=$4} END{print "磁盘可用容量:"sum/1024/1024"G"}'
1
统计/etc下文件总大小
ls -l /etc | awk '/^-/{sum+=$5} END{print "文件总大小:"sum/1024"M"}'
1
统计访问Nginx的各IP访问次数
awk ' \
{IP[$1]++} \
END { \
for (i in IP) {print i,IP[i]} \
}' /var/log/nginx/access.log
1
2
3
4
5
查看Nginx 1点到5点半的日志
awk -F"[: /]" '$7":"$8 >= "01:00" && $7":"$8 <="05:30"' /var/log/nginx/access.log
1
查看Docker容器的CPU使用率
docker stats jenkins --no-stream |awk 'NR==2{print $3}'
此部分来自:https://blog.csdn.net/anqixiang/article/details/117903529