awk
文本处理grep,sed,awk
grep 文本过滤器
sed 流编辑器
awk 文本处理报告生成器 (Aho,Kernighan,Werinberger),以定义好的格式显示出来
[[email protected] ~]# ls -l /usr/bin/awk lrwxrwxrwx. 1 root root 4 3月 28 20:26 /usr/bin/awk -> gawk
用法:
awk [options] ‘script‘ file1 file2....
awk [options] ‘pattern‘ ‘{action}‘ file1 file2...
输出:
一. -print
print item1,item2,...
1,各项目之间用逗号隔开,而输出以空白字符分隔,如果挨着写,则输出也是挨着,而且可以和print挨着;
[[email protected] ~]# cat awk.test This is a test [[email protected] ~]# awk ‘{print $1,$2,$3,$4}‘ awk.test This is a test [[email protected] ~]# awk ‘{print$1$2$3$4}‘ awk.test Thisisatest
2,指定分隔符号,在BEGIN模式指定,BEGIN后是花括号,圆括号算语法错误,分隔符号需要用双引号引起来,单引号算语法错误,
awk: cmd. line:1: BEGIN(OFS="#"){print $1,$2,$3,$4}awk: cmd. line:1: ^ syntax error[[email protected] ~]# awk ‘BEGIN{OFS="#"}{print $1,$2,$3,$4}‘ awk.test This#is#a#test[[email protected] ~]# awk ‘BEGIN{OFS=‘#‘}{print $1,$2,$3,$4}‘ awk.test awk: cmd. line:2: BEGIN{OFS=#}{print $1,$2,$3,$4}awk: cmd. line:2: ^ syntax error
3,可以在输出显示条目之间加入一些其他的输出字符,被当做独立的item,需要用双引号引起来,例如:
[[email protected] ~]# awk ‘BEGIN{OFS="#"}{print $1,$2,"TESTSTRING",$3,$4}‘ awk.test This#is#TESTSTRING#a#test
4,可以在输出的条目之间加入换行符,为多行输出:
[[email protected] ~]# awk ‘BEGIN{print "line one\nline two\nline three"}‘ line one line two line three
二,awk变量
awk内置变量之记录变量
FS:Field Separator 读取文件时使用的字段分隔符,默认是空白字符
RS:Record Separator 读取文件时使用的行分隔符,默认换行符
OFS:Output Field Separator 输出分隔符
ORS:Output Row Separator 输出换行符
awk内置变量之数据变量
NR:Number of input Records ,awk命令所处理的记录数,如果有多个文件,这个数目会把所处理的多个文件统一进行计数
NF:Number of Field 当前记录的field个数,总数,即容易理解$NF则表示最后一个字段
[[email protected] ~]# awk ‘{print NF}‘ awk.test 4
FNR:与NR不同的是,FNR用于记录正在处理的行是当前这一文件中被处理的行数(如有两个100行的文件,处理到第二各文件的第20行,NR=120,FNR=20)
[[email protected] ~]# awk ‘{print NR}‘ /etc/fstab /etc/issue 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [[email protected] ~]# awk ‘{print FNR}‘ /etc/fstab /etc/issue 1 2 3 4 5 6 7 8 9 10 11 1 2 3
ARGV:数组,保存命令行本身这个字符串,如awk ‘{print $0}‘ awk.test 这条命令中,AVGV[0] 保存awk,AVGV[1] 保存 awk.test
ARGC:awk命令行的参数个数
FILENAME:awk命令所处理的文件的名称
ENVIRON:当前shell环境变量及其值的关联数组:如
[[email protected] ~]# awk ‘BEGIN{print ENVIRON["PATH"]}‘ /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
用户自定义变量(2种方式)
gawk允许用户自定义变量以便在代码中用到,变量名命名规则和大多数的编程语言相同,只能用字母,数字,和下划线,且不能以数字开头,gawk变量名称区分字符大小写
a.在脚本中给变量赋值使用赋值语句进行:如
[[email protected] ~]# awk ‘BEGIN{var="variable testing";print var}‘ variable testing
b,也可以用-v 定义变量,且在awk中,变量不需要加$,在awk中$的意义是字段,在加BEGIN只执行一次,在{}的action中,语句和语句要使用分号隔开
[[email protected] ~]# awk -v var="varialbe testing" ‘BEGIN{print var}‘ varialbe testing
三,printf的使用
printf 命令格式: printf format item1,item2...
1,与print命令最大的不同是,printf需要指定格式
2,format用于指定后面每一个item的输出格式
3,printf不会自动打印换行符\n
format格式都以%开头
%c 显示字符的ASSII码
%d ,%i 十进制整数
%e ,%E 科学记数法显示数值
%f 显示浮点数
%g,%G 以科学计数法的格式或浮点数的格式显示数值
%s 显示字符串
%u 无符号的整数
%% 显示百分号自身
修饰符
N 显示宽度
- 左对齐(默认右对齐)
+ 显示数值符号
四 awk的操作符
算数操作符
-x 负值
+x 转换为数值
x^y 次方
x**y 次方
x/y 除
x+y
x-y
x%y
赋值操作符
=
+=
-=
*=
/=
%=
^=
**=
++
--
需要注意的是 如果某模式为=号 此时使用/*/ 肯能出现语法错误,应以/[=]/ 替代
布尔值
awk中,任何非0值或非空字符串都为真,反之就为假比较操作符
x < y True if x is less than y
x <= y True if x is less or equel to y
x > y True if x is greater than y
x > = y True if x is greater or equel to y
x == y True if x is equel to y
x !=y True if x is not equel to y
x ~ y True if the string x matches the regexp denoted by y
x !~y True if the string x does not match the regexp denoted by y
表达式间的逻辑关系符
&&
||
条件表达式
selector?if-true-exp:if-false-exp
函数调用
function_name (paral1,para2)
awk 常用模式
1 正则表达式 /regexp/
例如:显示以G开头的用户名
[[email protected] ~]# awk -F : ‘/^G/ {print $1}‘ /etc/passwd Gandefeng
2 表达式,其值为非0或非空字符串时满足条件
例如:显示使用bash的用户
[[email protected] ~]# awk -F : ‘$7~"bash$" {print $1,$7}‘ /etc/passwd root /bin/bash Gandefeng /bin/bash
例如;显示不为nologin的,格式输出
[[email protected] ~]# awk -F : ‘$7!~"nologin$" {printf "%-30s%-20s\n",$1,$7}‘ /etc/passwd root /bin/bash sync /bin/sync shutdown /sbin/shutdown halt /sbin/halt Gandefeng /bin/bash
3 匹配范围
例如:从第一个以uid为0开头的行到第一个以sync结尾的行
[[email protected] ~]# awk -F : ‘$3==0,$7~"sync" {printf "%-30s%-20s\n",$1,$7}‘ /etc/passwd root /bin/bash bin /sbin/nologin daemon /sbin/nologin adm /sbin/nologin lp /sbin/nologin sync /bin/sync
4 BEGIN/END模式,仅在awk的开头前运行一次和命令结束前最后一行处理完之后运行一次
例如:在上面实例基础上加首行
[[email protected] ~]# awk -F : ‘BEGIN{printf"%-10s%-10s%-20s\n","name","uid","shell"}$3==0,$7~"sync"{printf "%-10s%-10s%-20s\n",$1,$3,$7}END{print "end"}‘ /etc/passwd name uid shell root 0 /bin/bash bin 1 /sbin/nologin daemon 2 /sbin/nologin adm 3 /sbin/nologin lp 4 /sbin/nologin sync 5 /bin/sync end
5 空模式 文件的每一行都要做处理
和尾行,同时匹配,注意需要BEGIN需要在匹配的前面
常用的action
1 expression
2 control statements
3 compound statements
4 input statements
5 output statements
五 控制语句
1 if-else
if (condition) {then-body} else {[else-body]}
例如:判断管理员
awk -F : ‘{if($1=="root")print $1,"admin";else print $1,"common user"}‘ /etc/passwd
格式化输出
awk -F : ‘{if($1=="root")printf "%-15s:%s\n",$1,"admin";else printf "%-15s:%s\n",$1,"common user"}‘ /etc/passwd
统计uid大于500的用户
[[email protected] ~]# awk -F : -v sum=0 ‘{if($3>=500) sum++}END{print sum}‘ /etc/passwd 13
2 while
while (condition){statement1;statement2;...}
例:显示每一行字符串长度大于等于4的字段
awk -F : ‘{i=1;while(i<=NF) {if (length($i)>=4) {print $i};i++}}‘ /etc/passwd
3 do-while
do {statement1,statement2,...} while (condition)
awk -F : ‘{i=1;do {print $1,i++}while(i<=3)}‘ /etc/passwd
4 for
for ( variable assignment; condition; iteration process) {statement1,statement2...}
例:循环3次显示$1 遵循C语言风格
awk -F : ‘{for (i=1;i<=3;i++) print $1}‘ /etc/passwd
for 还可以遍历数组元素
例:遍历所有字段显示大于4的字段
awk -F : ‘{for (i=1;i<=NF;i++) {if (length($i)>=4) {print $i}}}‘ /etc/passwd
5 case
swith (expression) { case value or /regexp/: statement1,statement2,... default: statement1,....}
6 break和contiune 用于循环或case语句中的终止或继续
7 next 提前结束本行文本的处理,并接着处理下一行
例:显示ID为奇数的用户
awk -F : ‘{if($3%2==0) next;print $1,$3}‘ /etc/passwd
七 数组
awk数组的下标从1开始,也可自己定义,可以使用任意字符串作为下标
例:统计各shell出现次数
[[email protected] ~]# awk -F : ‘{shell [$NF]++}END{for(A in shell){print A,shell[A]}}‘ /etc/passwd /bin/sync 1 /bin/bash 2 /sbin/nologin 38 /sbin/halt 1 /sbin/shutdown 1
例:统计网络状态
[email protected] ~]# netstat -tan|awk ‘/^tcp/{state[$NF]++}END{for (A in state) print A,state[A]}‘ LISTEN 9 ESTABLISHED 2
例:统计日志文件IP地址的访问量
[[email protected] ~]# awk ‘{counts[$1]++};end {for (url in counts) print counts[url],url}‘ /var/log/httpd/access_log