awk用法

awk [options] 'script' file1, file2 ...
awk [options] 'PATTERN {action}' file1, file2 ...

PATTERN        模式
action        任何awk执行的内部语句




1.awk 常用内置变量

RS    记录分隔符
NF    当前记录的field个数
FS    字段分隔符,默认是空白字符
NR    awk命令所处理的记录数。
OFS    输出的段分隔符



awk 改变分隔符
awk -F: '{print $NF}' file        $NF 是指最后一个字段,这里意思就是以:为分隔符打印最后一个字段
awk -v FS=: '{print $NF}' file         -v 指定变量
awk -v OFS=: '{print $1,$2}' file
awk 'BEGIN{FS=":"}{print $1}' /etc/passwd    使用BEGIN模式进行赋值,需用“”


printf
printf 需要指定格式(format)

format格式的指示符都是%开头,后跟一个字符,如下:
%c    显示字符的ASCII 码
%d,%i    十进制整数
%e,%E    科学计数法显示数值
%f    显示浮点数
%g,%G    以科学计数法的格式或浮点数的格式显示数值
%s    显示字符串
%u    无符号整数
%%    显示%本身

修饰符
N:显示宽度
-:左对齐
+:显示数值符号

eg:
awk '{printf "%-5s%s\n", $1,$2}' file    以每段5个字符宽度显示$1,$2;并使字符串左对齐
   -  就是使字符串坐对齐
   5  就是字符宽度
   %s 限制字符串
   \n  printf不会自动打印换行符,需自己指定


2.awk字符串操作符

[root@master data0]# awk 'BEGIN{print "a" "b"}'
ab

将字符a和字符b连接在一起了


3.awk 比较操作符(< > <= >= == != ~ !~)
~ !~ 分别为匹配和不匹配

awk -F: '$1 ~ /root/ {print $1,$NF}' /etc/passwd
/etc/passwd某行的第一个字段包含root 则显示这行的第一个字段$1 和最后一个字段$NF

4.awk条件表达式

awk 'BEGIN{print(a>b)?"0":"1"}'
如果a>b 为真则显示0<?后面:前面的0>
如果a>b 为假 则显示:后面的1




awk模式

常见模式类型
1.Regexp:    正则表达式,格式为/regular expression/
2.expresssion    表达式,其值非0或非空字符时满足条件,如:$1 ~/root/ 或 $1 == "root",用运算符~ !~
3.Ranges    指定匹配范围,格式为 pat1,pat2
4.BEGIN/END    特殊模式,仅在awk执行命令前运行一次或者结束前运行一次
5.Empty(空模式)    匹配任意输入行


eg:
1.awk -F: '/bash/{print $0}' /etc/passwd    打印/etc/passwd 中包含bash的行

2.awk -F: '$3>=500{print $1,$3}' /etc/passwd    打印/etc/passed中用户id($3)大于等于500的用户名和用户id
 awk -F: '{if($3=="1")print $1,$3}' /etc/passwd

3.awk -F: '/root/,/rpc/{print $1,$3}' /etc/passwd    打印第一次匹配到root和第一次匹配到rpc的时候中间所有行

4.awk -F: 'BEGIN{print "UserName     UID"};{printf "%-15s%s\n", $1,$3};END{print "OVER!!"}' /etc/passwd
    在后面真正显示用户和用户id之前先打印一个头部 UserName和UID,也就是在执行后面printf的时候先执行前面的print,在显示完用户id之后在打印一个OVER

awk多个print的时候使用;隔开即可,以下两种结果是一样的
awk -F: '{print $1;print $3}' /etc/passwd
awk -F: '{print $1};{print $3}' /etc/passwd  


常用action  awk循环是针对单行的

if语句
语法:    if (condition) {then-body} else {else-body}
awk -F: '{if($3==0)print $1,"Admin"; else print $1,"Common User"}' /etc/passwd
awk -F: '{if($3==0)printf "%-15s%s\n", $1,"Admin"; else printf "%-15s%s\n", $1,"Common User"}' /etc/passwd

while循环
语法:    while (condition) {statement1;statement2;....}
awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd

do-while 循环
语法:    do {statement1;statement2;....} while (condition)
awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd

for循环
语法:    for (variable assignment;condition;iteration process)
awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd

最常用for寻混遍历数组元素
语法:    for (i in array) {statement1;statement2;....}
[root@master data0]# awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%-15s:%i\n",A,BASH[A]}}' /etc/passwd
/sbin/shutdown :1
/bin/bash      :3
/sbin/nologin  :30
/sbin/halt     :1
/bin/sync      :1



使用awk统计服务器连接各种状态
netstat -nat | awk '$1~/tcp/{S[$NF]++}END{for (A in S) print A,S[A]}'
netstat -ant |awk '$1=="tcp"{S[$NF]++}END{for (A in S) printf "%-15s%s\n", A,S[A]}'

使用awk统计apache访问日志中哪个ip访问次数最多
awk '{IP[$1]++}END{for(A in IP) print A,IP[A]}' access_log