awk学习笔记:
好文章推荐:http://5142926.blog.51cto.com/5132926/967141
(一)print的使用:
查找系统中拥有管理权限的用户信息:
# awk -F: '{if($3==0) print}' /etc/passwd 精确匹配
# awk -F: '{if($3~/0/) print}' /etc/passwd 不精确匹配
查找系统中非管理员用户信息:(若只想显示用户名称,刚在print后加上$1即可)
# awk -F: '{if($3!=0) print}' /etc/passwd 精确不匹配
# awk -F: '{if($3!~/0/) print}' /etc/passwd 不精确不匹配
取出系统中用户是root且uid是0的用户信息:
# awk -F: '{if($1=="root"&&$3=="0")print}' /etc/passwd
改变分隔符,用到了FS这个变量:
#awk -v FS=: '{print $NF}' /etc/passwd = awk -F: '{print $NF}' /etc/passwd
显示指定文件中的第一和第7个字段,字段间用“:”号隔开,用到了OFS这个变量:
# awk -F: '{print $1,$7}' /etc/passwd | awk -v OFS=: '{print $1,$2}'
(二)printf的使用:
# awk -F: '{if($3==0) printf ("%-10s%s\n",$1,"admin");else printf ("%-10s%s\n",$1,"common user")}' /etc/passwd
格式:awk [option] '{printf("format1format2",item1,item2)}' file
要点
1、与print命令的最大不同是,printf要指定format
2、format与后边的item一一对应
3、换行符要单独打印:\n
format格式的指示符都以%开头,后跟一个字符:
%% 表示显示%自身,用于转义
%d 十进制有符号整数
%u 十进制无符号整数
%f 浮点数
%s 字符串
%c 单个字符
%p 指针的值
%e 指数形式的浮点数
%x, %X 无符号以十六进制表示的整数
%0 无符号以八进制表示的整数
%g 自动选择合适的表示法
\n 换行
\f 清屏并换页
\r 回车
\t Tab符
\xhh 表示一个ASCII码用16进表示,其中hh是1到2个16进制数
说明:
(1). 可以在"%"和字母之间插进数字表示最大场宽。
例如: %3d 表示输出3位整型数, 不够3位右对齐。
%9.2f 表示输出场宽为9的浮点数, 其中小数位为2, 整数位为6,小数点占一位, 不够9位右对齐。
%8s 表示输出8个字符的字符串, 不够8个字符右对齐。
如果字符串的长度、或整型数位数超过说明的场宽, 将按其实际长度输出.但对浮点数, 若整数部分位数超过了说明的整数位宽度, 将按实际整数位输出;若小数部分位数超过了说明的小数位宽度, 则按说明的宽度以四舍五入输出.
另外, 若想在输出值前加一些0, 就应在场宽项前加个0。
例如: %04d 表示在输出一个小于4位的数值时, 将在前面补0使其总宽度为4位。
如果用浮点数表示字符或整型量的输出格式, 小数点后的数字代表最大宽度,小数点前的数字代表最小宽度。
例如: %6.9s 表示显示一个长度不小于6且不大于9的字符串。若大于9, 则第9个字符以后的内容将被删除。
(2). 可以在"%"和字母之间加小写字母l, 表示输出的是长型数。
例如: %ld 表示输出long整数
%lf 表示输出double浮点数
(3). 可以控制输出左对齐或右对齐, 即在"%"和字母之间加入一个"-" 号可说明输出为左对齐, 否则为右对齐。
例如: %-7d 表示输出7位整数左对齐
%-10s 表示输出10个字符左对齐
例子:
df -h > dffile
more dffile
Filesystem Size Used Avail Use% Mounted on
/dev/hda1 15G 5.1G 8.7G 37% /
none 252M 0 252M 0% /dev/shm
/dev/hda6 31G 12G 18G 40% /home
/dev/hda3 15G 1.7G 13G 13% /usr
/dev/hda2 15G 152M 14G 2% /var
awk '{printf ("%12s\n",$1)}' dffile
Filesystem
/dev/hda1
none
/dev/hda6
/dev/hda3
/dev/hda2
awk '{printf ("%-12s\n",$1)}' dffile
Filesystem
/dev/hda1
none
/dev/hda6
/dev/hda3
/dev/hda2
例子:
echo 1.7 > 2
awk '{printf ("%d\n",$1)} 2
1
awk '{printf ("%f\n",$1)}' 2
1.700000
awk '{printf ("%3.1f\n",$1)}' 2
1.7
awk '{printf ("%4.1f\n",$1)}' 2
1.7
awk '{printf ("%e\n",$1)}' 2
1.700000e+00
取出系统中用户名与shell路径,如果用户名匹配到root,刚按照规定的格式输出这个用户的用户名与shell:
# awk -F: 'BEGIN{print "USERNAME SHELL"}{name=$1; shell=$7; if(name~/root/) printf("%-10s%s\n",name,shell)}' /etc/passwd
如果对输出格式无要求,可以把printf("%-10s%s\n",name,shell)更换为print name,shell
计算当前目录下各文件的大小及全部文件大小的总和:
# ls -l|awk '/^[^d]/{printf("%-20s%s\n",$9,$5)}{tot+=$5}END{print "total kb:"tot}'
内置变量:
ARCC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FNR 浏览文件的记录数
FS 置顶分隔符,等价于-F
NF 浏览记录的域的个数
NR 已读的记录数(行数)
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
这里要注意“NF”与“NR”的区别
(三)常见的模式匹配类型:
1、regexp:正则表达式,模式为/regular expression/
# awk -F: '/bash/{print $0}' /etc/passwd 处理流程:当指定文件中能匹配到bash字符串时,才执行后边{print $0}
2、表达式,用操作符连接起来的
# awk -F: '$3>=500{print $1}' /etc/passwd
# awk -F: '$3~0{print $0}' /etc/passwd 如果匹配文件中的第三个字段有0,刚把这一行都显示出来.这是不精确的匹配,可以匹配0,10等
# awk -F: '$3==0{print $0}' /etc/passwd 7这里是精确匹配
3、ranges:指定匹配范围
# cat /etc/fstab | awk '/tmpfs/,/sysfs/{print}'
4、BEGIN/END
以打印报头报尾的方式,取出系统中的所有用户及UID:
# awk -F: 'BEGIN{print "USER UID"}{printf("%-10s%s\n",$1,$3)}END{print "This is all users!"}' /etc/passwd
(四)循环词句的使用
1、while
语法: while (condition){statement1;statement2;……}
# awk -F: '{i=1;while (i<=3){print $i;i++}}' /etc/passwd 只显示前三个字段
# awk -F: '{i=1;while (i<=NF) {print $i;i+=2}}' /etc/passwd 只显示奇数字段
2、do……while 先执行一次,再判断
语法: do {statement1,statement2,……} while (condition)
# awk -F: '{i=1;do {print $i;i++} while (i<=3)}' /etc/passwd
3、for 对循环次数已知的循环
# awk -F: '{for (i=1;i<=3;i++) print $i}' /etc/passwd 显示前三个字段
# awk -F: '{for(i=1;i<=NF;i+=2) print $i}' /etc/passwd 显示奇数字段
(五)awk中使用数组
# awk 'BEGIN{A["X"]="XX";A["Y"]="YY";print A["X"],A["Y"]}' 打印出XX YY
# awk 'BEGIN{A[1]="XX";A[2]="YY";print A[1],A[2]}'
for (A in ARRAY){print ARRAY[A]} 用变量的方式打印出数组中的每一个元素
# awk 'BEGIN{A["X"]="XX";A["Y"]="YY";for (B in A) print A[B]}' 这里的B相当于数组A的下标
# netstat -ant | awk '$1~/tcp/{A[$NF]++}END{for (B in A) print B,A[B]}' 此语句是统计系统上基于tcp协议的监听情况
# netstat -ant | awk '$1~/tcp/{A[$NF]++}END{for (B in A) printf ("%-11s:%s\n",B,A[B])}'
# awk '{IP[$1]++}END{for (M in IP) print M,IP[M]}' access_log 统计apache访问日志的各ip的访问次数
gsub函数:
# awk -F: '{gsub(/^root/,"test");print}' user
# awk 'gsub(/^root/,"netseek") {print}' user
http://bbs.chinaunix.net/thread-2312439-1-1.html