GNU awk:
文本处理三工具:grep, sed, awk
grep, egrep, fgrep:文本过滤工具;pattern
sed: 行编辑器
模式空间、保持空间
awk:报告生成器,格式化文本输出;
awk是指向gawk(GNU/AWK)的一个软链接
[root@bogon ~]# ll /bin/awk lrwxrwxrwx. 1 root root 4 Mar 16 08:30 /bin/awk -> gawk
基本用法:
gawk [options] 'program' FILE ...
program: PATTERN{ACTION STATEMENTS}
语句之间用分号分隔
print, printf
print输出指定内容后换行,printf只输出指定内容后不换行
选项:
-F:指明输入时用到的字段分隔符;
-v var=value: 自定义变量;
1、print
print item1, item2, ...
要点:
(1) 逗号分隔符;
(2) 输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式;
(3) 如省略item,相当于print $0;
显示/etc/passwd文件中第一个和第三个字符串
[root@bogon ~]# awk -F: '{print $1,$3}' /etc/passwd
2、变量
2.1 内建变量
FS:input field seperator,默认为空白字符;
OFS:output field seperator,默认为空白字符;
指定分隔符为:,同时指定,输出时的分隔符也为:
[root@bogon ~]# awk -v FS=':' -v OFS=':' '{print $1,$3}' /etc/passwd
RS:input record seperator,输入时的换行符;
ORS:output record seperator,输出时的换行符;
[root@bogon ~]# awk -v RS=' ' '{print}' /etc/passwd
NF:number of field,字段数量
{print NF}字段数量
{print $NF}最后一个字段
[root@bogon ~]# awk -F: '{print NF}' /etc/passwd [root@bogon ~]# awk -F: '{print $NF}' /etc/passwd
NR:number of record, 行数;
FNR:各文件分别计数;行数;
[root@bogon ~]# awk '{print FNR}' /etc/passwd
FILENAME:当前文件名;
ARGC:命令行参数的个数;
ARGV:数组,保存的是命令行所给定的各参数;
[root@bogon ~]# awk 'BEGIN{print ARGC}' /etc/passwd /etc/fstab 3 [root@bogon ~]# awk 'BEGIN{print ARGV[0]}' /etc/passwd /etc/fstab awk
2.2 自定义变量
(1) -v var=value
变量名区分字符大小写;
[root@bogon ~]# awk -v test="hello" 'BEGIN{print test}'
(2) 在program中直接定义
[root@bogon ~]# awk 'BEGIN{test="hello";print test}' hello
3、printf命令
格式化输出:printf FORMAT, item1, item2, ...
(1) FORMAT必须给出;
(2) 不会自动换行,需要显式给出换行控制符,\n
(3) FORMAT中需要分别为后面的每个item指定一个格式化符号;
格式符:
%c: 显示字符的ASCII码;
%d, %i: 显示十进制整数;
%e, %E: 科学计数法数值显示;
%f:显示为浮点数;
%g, %G:以科学计数法或浮点形式显示数值;
%s:显示字符串;
%u:无符号整数;
%%: 显示%自身;
[root@bogon ~]# awk -F: '{printf "username:%10s id:%s\n",$1,$3}' /etc/passwd username: root id:0 username: bin id:1 username: daemon id:2 username: adm id:3 ... ...
修饰符:
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度;
%3.1f:3个字符的宽度,.后面表示小数点后的精度。
-: 左对齐
[root@bogon ~]# awk -F: '{printf "username:%-10s id:%d\n",$1,$3}' /etc/passwd
+:显示数值的符号
4、操作符
算术操作符:
x+y, x-y, x*y, x/y, x^y, x%y
-x
+x: 转换为数值;
字符串操作符:没有符号的操作符,字符串连接
赋值操作符:
=, +=, -=, *=, /=, %=, ^=
++, --
比较操作符:
>, >=, <, <=, !=, ==
模式匹配符:
~:是否匹配
!~:是否不匹配
逻辑操作符:
&&
||
!
函数调用:
function_name(argu1, argu2, ...)
条件表达式:
selector?if-true-expression: if-false-expression
显示id号大于500的
[root@bogon ~]# awk -F: '$3>500{print $1,$3}' /etc/passwd
查看id号大于500的输出为common user,否则为system user。
[root@bogon ~]# awk -F: '{$3>=500?usertype="common user.":usertype="system user.";printf "%-10s:%s\n",$1,usertype}' /etc/passwd
5、PATTERN(模式)
(1) empty:空模式,匹配每一行;
(2) /regular expression/:仅处理能够被此处的模式匹配到的行;
(3) relational expression: 关系表达式;结果有“真”有“假”;结果为“真”才会被处理;
真:结果为非0值,非空字符串;
(4) line ranges:行范围,
startline,endline:/pat1/,/pat2/
注意: 不支持直接给出数字的格式
例如:显示/etc/passwd中2-10行之间的内容
[root@bogon ~]# awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
(5) BEGIN/END模式
BEGIN{}: 仅在开始处理文件中的文本之前执行一次;
END{}:仅在文本处理完成之后执行一次;
[root@bogon ~]# awk -F: 'BEGIN{print " username uid \n-----------------\n"}{printf "%-10s %d\n",$1,$3}END{print "=============\nend "}' /etc/passwd username uid ----------------- root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 uucp 10 operator 11 games 12 gopher 13 ftp 14 nobody 99 dbus 81 vcsa 69 abrt 173 haldaemon 68 ntp 38 saslauth 499 postfix 89 sshd 74 tcpdump 72 apache 48 ============= end
6、常用的action(了解)
(1) Expressions
(2) Control statements:if, while等;
(3) Compound statements:组合语句;
(4) input statements
(5) output statements
7、控制语句
if(condition) {statments}
if(condition) {statments} else {statements}
while(conditon) {statments}
do {statements} while(condition)
for(expr1;expr2;expr3) {statements}
break
continue
delete array[index]
delete array
exit
{ statements }
7.1 if-else
语法:if(condition) statement [else statement]
用户id大于1000输出为普通用户,否则输出为系统用户
[root@bogon ~]# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "Sysuser: %s\n",$1}}' /etc/passwd
找出以/bin/bash登录的用户
[root@bogon ~]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
某个行的字段数大于5个才显示
[root@bogon ~]# awk '{if(NF>5) print $0}' /etc/fstab
查看某设备使用率超过20%的
[root@bogon ~]# df -h | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>=20) print $1}'
使用场景:对awk取得的整行或某个字段做条件判断;
7.2 while循环
语法:while(condition) statement
条件“真”,进入循环;条件“假”,退出循环;
使用场景:对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用;
查看/etc/grub.conf里以n个空格开头的,后面跟kernel的行,分别统计某个自段的字符个数
[root@bogon ~]# awk '/^[[:space:]]*kernel/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub.conf
只显示大于等于7个的
[root@bogon ~]# awk '/^[[:space:]]*kernel/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /etc/grub.conf
7.3 do-while循环
语法:do statement while(condition)
意义:至少执行一次循环体
7.4 for循环
语法:for(expr1;expr2;expr3) statement
for(variable assignment;condition;iteration process) {for-body}
[root@bogon ~]# awk '/^[[:space:]]*kernel/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub.conf
特殊用法:
能够遍历数组中的元素;
语法:for(var in array) {for-body}
7.5 switch语句
语法:switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement}
7.6 break和continue
break [n]
continue
提前结束对本行的处理而直接进入下一行;
显示id为偶数的用户
[root@bogon ~]# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
8、array
关联数组:array[index-expression]
index-expression:
(1) 可使用任意字符串;字符串要使用双引号;
(2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”;
若要判断数组中是否存在某元素,要使用"index in array"格式进行;
数组下标可以自定义
weekdays[mon]="Monday"
若要遍历数组中的每个元素,要使用for循环;
for(var in array) {for-body}
[root@bogon ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
注意:var会遍历array的每个索引;
state["LISTEN"]++
state["ESTABLISHED"]++
统计每种监听状态的次数
[root@bogon ~]# netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) { print i,state[i]}}'
[root@bogon ~]# awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
练习1:统计/etc/fstab文件中每个文件系统类型出现的次数;
[root@bogon ~]# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab
练习2:统计指定文件中每个单词出现的次数;
[root@bogon ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
9、函数
数值处理:
rand():返回0和1之间一个随机数;
字符串处理:
length([s]):返回指定字符串的长度;
sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;
gsub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现均替换为s所表示的内容;
split(s,a[,r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中;
[root@bogon ~]# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'
9.2 自定义函数
本文出自 “我的学习笔记” 博客,请务必保留此出处http://zhaoyongtao.blog.51cto.com/10955972/1761362