一、awk简介
awk的意思是报告生成器,能根据输入信息,把信息格式化后显示,继而出现new awk(nawk)在windows上实现,gawk,awk实现在linux上。awk是一种编程语言,在linux/unix下对文本和数据进行处理,是一款强大编程工具。在命令行中使用,更多作为脚本来使用。
awk处理文件和数据的方式:逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行操作。如果没有指定处理动作,则把匹配行打印,如果没有指定模式,则所有行都处理。gawk是awk的GNU版本。可通过命令ll `which awk`查看
Linux文本处理三剑客:
grep, egrep, fgrep: 文本过滤器
sed: 文本编辑(行编辑器)
awk: 文本格式化,报表生成器
awk工作过程
根据定义的模式,一次从文本中读取一行,awk会对行做相应的切片,将每一行按照分割符进行切割。例如this is a test 使用空白字符做分隔符将它们分开,切割为this,is,a,test四个片,可以使用变量,分别对应为$1,$2,$3,$4代表四个切割片
二、awk用法
1、基本格式
gawk [options] ‘program‘ file file ...
program程序: PATTERN { ACTION STATEMENT }
由语句组成,语句分隔符是";"
ACTION: print, printf
选项options:
-F[]:指明输入字段分隔符;默认以空白为分隔符
-F[, ]:逗号或空格为分隔符
-v var=val: 变量赋值,无须声明,可直接调用
-f /path/from/awk_script
EX:
(1)、打印/etc/passwd中的第三行和第六行不同用法
#awk -F: ‘{print $3,$6}‘ /etc/passwd #awk -F: -v f1=3 -v f2=6 ‘{print $f1,$f2}‘ /etc/passwd #awk -v FS=‘:‘ ‘{print $3,$6}‘ /etc/passwd
(2)、运行awk脚本
#vim awk.script {print $1,$3} #awk -f awk.script -F: /etc/passwd
2、awk的输出命令print
print item1, item2, ...
item:
(1)字符串:用引导引用
print "htello","world"
(2)变量:显示变量的值
print name
要点:
(1)item间用逗号,输出为空白字符
(2)item可以为字符串、变量、数值等
(3)item如果省略,等于print $0
(4)输出空白字符,print ""
EX:打印/etc/passwd中的所有用户
#awk -F: ‘{print "user is",$1}‘ /etc/passwd
3、变量
3.1 内置变量
(1)FS: input field seperator,输入字段分隔符,默认为空白字符;
#awk -v FS=":" ‘{print $1,$3}‘ /etc/passwd #vim awk.txt This is the first line. Here you are. This is tomas,jason. #awk ‘{print $3}‘ awk.txt #awk -v FS="[ ,]" ‘{print $3}‘ awk.txt //输出以逗号或空白字符为分隔符的字段
(2)RS:input record separator,输入行分隔符 默认为换行符;
#awk -v RS=" " ‘{print $0}‘ /etc/passwd
(3)OFS: output field separator,输出字段分隔符,默认为空白字符;
#awk -v FS=":" -v OFS=":" ‘{print $1,$3,$7}‘ /etc/passwd //输出字段分隔符也为":"
(4)ORS:output record separator,输出行分隔符, 默认为换行符;
#awk -v RS=" " -v ORS=" " ‘{print $0}‘ /etc/passwd
(5)NF: number of field in current record,当前行的字段数;
#awk ‘{print NF}‘ /etc/issue //打印行数 #awk ‘{print $NF}‘ /etc/issue //打印行最后字段
(6)NR:行数,所有文件统一计数;
#awk ‘{print NR}‘ /etc/issue
(7)FNR:行数,各文件分别计数;
#awk ‘{print FNR}‘ /etc/fstab /etc/issue
(8)FILENAME:当前被读取的文件名
#awk ‘{print NR,FILENAME}‘ /etc/issue
(9)ARGC:命令行参数的个数;
#awk ‘{print ARGC}‘ /etc/issue //这里显示为两个参数,包括print和文件名
(10)ARGV:数组,保存了命令行参数自身
#awk ‘{print ARGV[0]}‘ /etc/issue //参数为print和文件名,但是输出ARGV[0],则显示为awk
3.2 自定义变量
-v var=val:
变量名命名规则:
区分字符大小写
数字,字符,下划线,不能以数字开头
不能使用内置关键字
定义变量的位置:
(1) 可以program中定义变量;
(2) 通过-v选项定义变量;
#awk ‘BEGIN{FS=":";f1=1}{print $f1}‘ /etc/passwd //只在开始赋值一次 #awk -F: ‘{f1=1;print $f1}‘ /etc/passwd //每行都要赋值
4、printf命令
格式: printf format, item1, item2, ...
(1)要点:
(1) format是必须的;
(2) 不自动换行,需给换行符;\n
(3) 为每个item指定格式符;否则item无法显示
(2)格式符:都以%开头,后跟一个字符
%c: 显示字符的ASCII码;
%d,%i: 显示十进制整数;
%e, %E: 科学计数法显示数值;
%f: 显示为浮点数;
%g, %G: 以科学计数法格式或浮点数格式显示数值;
%s: 字符串
%u: 无符号的整数
%%: 显示%自身
#awk -F: ‘{printf "This is user: %s.\n",$1}‘ /etc/passwd #awk -F: ‘{printf "This is user: %s,his UID is %d.\n",$1,$3}‘ /etc/passwd
(3)修饰符:
#[.#]: 第一个#指定显示宽度,例如%30s;第二个#表示小数点后的精度;
-: 左对齐,默认为右对齐
+:显示数值符号
#awk -F: ‘{printf "This is user: %s,his UID is %-20f.\n",$1,$3}‘ /etc/passwd //UID显示为20个字符并且精度为2 #awk -F: ‘{printf "%20s:%-d\n",$1,$3}‘ /etc/passwd
5、操作符:
(1)算术操作符:
x+y, x-y, x*y, x/y, x^y, x%y
-x: 负值
+x: 转换为数值
#awk ‘BEGIN{print 4*5}‘
(2)字符串操作:字符串连接
#awk ‘BEGIN{print "hello" "awk"}’
(3)赋值操作符:
=, +=, -=, *=, /=, %=, ^=
++, --
#awk -v f1=3 ‘BEGIN{f1*=6;print f1}‘
(4)比较操作符:
>, >=, <. <=, ==, !=
(5)模式匹配符:
~:能匹配为真
!~:不能匹配为真
(6)逻辑操作符:
&& 与运算
|| 或运算
(7)条件表达式:
selector?if-true-expression:if-false-expression
相当于bash的:
if SELECTOR;then
if-true-expression
else
if-false-expression
# awk -F: ‘{$3>=500?usertype="common user":usertype="sysuser or admin";printf "%20s:%-s\n",$1,usertype}‘ /etc/passwd #df -h | awk ‘{printf "%30s:%-s\n",$1,$5}‘
(8)函数调用:
function_name(argu1,argu2,...)
6、PATTERN
(1) /regular expression/: 正则表达式,仅处理能够被/regular expression/所匹配到的行;
#awk -F: ‘/^[ab]/{print $1,$3}‘ /etc/passwd
(2) relational expression:关系表达式,有真假之分,一般来说,其结果为非0或非空字符串时为“真”,否则,为“假”;
#awk -F: ‘$3>=500{print $1,$3}‘ /etc/passwd //打印UID大于和等于500的用户名和UID #awk -F: ‘$1~/root/{print $1,$3}‘ /etc/passwd //打印用户名包含root的用户名和UID
(3) line ranges:行范围,类似sed或vim的地址定界法;startline, endline
(4) BEGIN/END: 特殊模式
BEGIN:程序执行前执行一次
END:程序执行后执行一次
#awk -F: ‘BEGIN{printf "%20s:%-s\n","UserName","UserID"}{printf "%20s:%-d\n",$1,$3}END{print "--------\nprogram is end"}‘ /etc/passwd #awk ‘BEGIN{FS=":"}{print $1,$3}‘ /etc/passwd
(5) empty: 空模式,匹配任意行;
#awk -F: ‘{print $1,$NF}‘ /etc/passwd
7、常用的action
(1) Expressions 表达式,如变量赋值
(2) Control statements 控制语句,如if,while等
(3) Compound statements 复合语句,如{}
(4) input statements 输入语句
(5) output statements 输出语句
8、控制语句
if (condition条件) { statement语句 } [ else statement ]
while (condition) { statement }
do statement while (condition)
for (expr1初值; expr2循环; expr3修正) statement
for (var in array) statement
switch (expression) {case VALUE or /REGEXP/:statement;...;default;statement}
break 结束循环
continue 结束本轮循环
delete array[index]
delete array
exit [ expression ]
{ statements }
8.1 if-else
语法:if (condition条件) statement [ else statement ]
if (condition) { statements; } [ else { statements; }]
# awk -F: ‘{if ($3>=500) print $1," is a common user." }‘ /etc/passwd # awk -F: ‘{if ($3>=500) {print $1," is a common user."} else {print $1," is a system user or admin."}}‘ /etc/passwd # awk ‘{if (NF>6) print NF, $0 }‘ /etc/inittab
用法:对awk取得的整行或行中的字段做条件判断;
8.2 while循环
语法:while (condition) statement
while (condition) { statements }
条件为真时进行循环,直到为假退出;
用法:通常用于在当前行的各字段间进行循环;
# awk ‘{i=1;while(i<=NF){printf "%20s:%d\n",$i,length($i); i++}}‘ /etc/inittab //打印每行字段名称和字段长度 # awk ‘{i=1;while(i<=NF){if (length($i)>5) {printf "%20s:%d\n",$i,length($i);} i++}}‘ /etc/inittab //查找打印在文件/etc/inittab下每行字段长度大于5的字段名称和长度
8.3 do-while循环 了解
语法:do statement while (condition)
do { do-while-body } while (condition)
意义:至少执行一次循环体;
8.4 for循环
语法:for (expr1; expr2; expr3) statement
for (expr1; expr2; expr3) { statements }
for (varaiable assignment; condition; iteration process) { for-body }
#awk ‘{for(i=1;i<=NF;i++){if(length($i)>=6) print $i}}‘ /etc/issue //查找文件/etc/issue字段长度大于等于6并打印字段 #awk ‘{for(i=1;i<=NF;i++) {printf "%s:%d\n", $i, length($i)}}‘ /etc/inittab
for循环在awk中有一个专用于遍历数组元素:
语法:for (var in array) { for-body }
8.5 switch 了解
语法:switch (expression) {case VALUE or /REGEXP/: statement; ...; default: statementN}
8.6 break and continue
break [n]: 退出当前循环,n表示几层循环
continue:提前结束本轮循环,直接进入下轮循环
8.7 next
提前结束对本行的处理而进入下一行的处理
# awk -F: ‘{if($3%2==0) next;print $1,$3}‘ /etc/passwd //打印UID为奇数的行的1和3字段,对UID取模,如果等于0则执行next进入对下一行的处理,如果不等于0则执行一条语句打印$1和$3字段
9、Array 数组
关联数组:array[index-expression]
index-expression: 索引表达式
可以使用任意字符串;
如果某数组元素事先不存在,在引用时,awk会自动创建此元素并将其值初始化为空串;
因此,若要判断数组是否存在某元素,要使用“index in array”进行;
要遍历数组中的每个元素,要使用: for (var in array) ,var会遍历array的每个索引,所以,要显示数组元素的值,要使用array[var]
weekdays
weekdays[mon]="Monday"
weekdays[tue]="tuesday"
...
for(i in weekdays) 此时i会遍历weekdays数组的每个索引,即mon,tue,而非元素的值"Monday"或"Tuesday"等
要获取元素的值:weekdays[i]
EX:统计每一行中各单词分别出现的次数
可定义一个数组,用单词本身当索引,而元素的值存储单词出现的次数
# awk ‘{for(i=1;i<=NF;i++) {count[$i]++}}END{for(j in count) {print j,count[j]}}‘ awk.txt //统计文本中每个单词及出现的次数,第一个for定义数组,第二个for遍历数组 # awk ‘{for(i=1;i<=NF;i++) {count[$i]++}}END{for(j in count) {print j,count[j]};delete count}‘ awk.txt //分别统计每行每个单词及出现的次数 # ss -tan | awk ‘!/^State/{state[$1]++}END{for (i in state) {print i,state[i]}}‘ //统计TCP连接各状态名称及个数 #awk ‘{ip[$1]++}END{for(i in ip)print i,ip[i]}‘ /var/log/httpd/access_log //统计web被访问的IP及次数 # netstat -tan | awk ‘/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}}
10、函数
(1)内置函数
1)数值处理:
rand(): 返回0和1之间一个随机数;
#awk ‘BEGIN{print rand()}‘
2)字符串处理:
ength([s]): 返回指定字符串的长度
#awk ‘BEGIN{print length("hello")}‘
3)sub(r, s [, t])查找r在t中,把每行第一次出现的r替换为s
sub(ab,AB,$0)
#vim count.txt How are you? How old are you? #awk ‘{sub("are","ARE",$0);print $0}‘ count.txt
4)gsub(r, s [, t]):查找r在t中,把所有出现的r替换为s
5)split(s, a [, r]): 以r为分隔符,s为字符串切割,并把结果保存到a中
注意:awk的数组下标从1开始编号
#awk ‘{split($0,userinfo,":");print userinfo[1]}‘ /etc/passwd //以":"为分隔符,$0为字符串切割,并把结果保存到userinfo中 # netstat -tan | awk ‘/^tcp/{len=split($5,client,":");ip[client[len-1]]++}END{for(i in ip){print i,ip[i]}}‘
6)substr(s, i [, n]): 从s表示的字符串中取子串,从i开始,取n个字符;
7)时间类的函数:
systime(): 取时间戳;
8)位运算函数:
and(v1,va2):
(2)自定义函数
function f_name(p,q)
{
...
}
本文出自 “蜗牛” 博客,请务必保留此出处http://linuxkingdom.blog.51cto.com/6334977/1653376
原文地址:http://linuxkingdom.blog.51cto.com/6334977/1653376