awk简介
awk是一种编程语言,也可以说是一个脚本语言解释器,主要是用来实现文本的格式化输出。awk是取了其三位作者名字的首字母,即Aho
,Weinberger
和Kernighan
。awk在Linux上是基于GNU协议实现的,即GNU awk,也就是gawk。
awk的工作模式
遍历整个文件,从第一行到最后一行。每次仅读取文件的一行,依照用户指定的输入分隔符进行切片,并将每个分片在awk的内存空间赋予一个内建变量(位置变量)进行保存,然后根据用户指定的pattern寻找匹配特定模式的行,执行处理过程。
awk基本语法格式
gawk [OPTIONS] 'PATTERN{ACTION_STATEMENTS}' FILE...
-
NOTE
-
PATTERN可以是BEGIN、END、表达式等;
-
PATTERN省略则表示匹配所有数据;
-
ACTION_STATEMENT语句之间使用分号分隔;
-
默认的ACTION是print。
OPTIONS
-
-F fs,–field-separator fs:指明以fs作为输入行的字段分隔符,默认分隔符为空格;
-
-v var=val,–assign var=val:自定义一个变量;
-
-f program-file,–file program-file:指明从指定的脚本文件中读取awk指令。
变量
内建变量
FS:input Field Separator,输入的字段分隔符,默认为空格; OFS:Output Field Separator,输出的字段分隔符,默认为空格; RS:input Record Separator,输入时的换行符,默认为\n; ORS:Output Record Separator,输出时的换行符,,默认为\n; NF:Number of Field,当前行的字段数量; NR:Number of Record,输入流的当前记录编号(行数); FNR:当前输入文档的当前记录编号,多个输入文档时有用; FILENAME:当前输入文件名; ARGC:命令行参数的个数; ARGV:一个数组,保存命令行所给定的各参数。
实例
指明输入的字段分隔符:
# awk -F: '{print $1,$3}' /etc/passwd -->//指定的字段分隔符可以使用引号引起,也可以不用(空格除外),引号可以是单双引号; # awk -v FS=':' '{print $1,$3}' /etc/passwd -->//指定的字段分隔符可以使用引号引起,也可以不用(空格除外),引号可以是单双引号; # awk 'BEGIN{FS=":"}{print $1,$3}' /etc/passwd -->//指定的字段分隔符只能使用双引号引起。
NOTE: 指明多个分隔符时使用[],如FS="[:,]"。
自定义变量
-
变量名区分字母大小写;
-
可以在ACTION_STATEMENT中定义;
-
可以在命令行中通过-v选项定义。
实例
# awk -v test='hello gawk' 'BEGIN{print test}' -->//指明变量值时可以使用单双引号; # awk 'BEGIN{test="hello gawk";print test}' -->//指明变量值时只能用双引号。
NOTE
在引用变量时不要加$
符号。
print命令
print item1,item2...
-
NOTE
-
以逗号作为分隔符;
-
输出的各item可以是字符串、数值,也可以是当前记录的字段、变量或awk的表达式;
-
如果省略item,相当于print $0。
printf命令:格式化输出
printf FORMAT, item1, item2, ...
-
NOTE
-
FORMAT必须给出;
-
不会自动换行,必须显式给出换行控制符\n;
-
FORMAT中需要分别为后面的每个item指定一个格式化符号。
格式符
%c: 显示字符的ASCII码; %d, %i: 显示十进制整数; %e, %E: 科学计数法数值显示; %f:显示为浮点数; %g, %G:以科学计数法或浮点形式显示数值; %s:显示字符串; %u:无符号整数; %%: 显示%自身;
修饰符
#[.#]:第一个数字#控制显示宽度;第二个数字#表示小数点后边的精度;例如,%3.3f。 +:显示数值的符号 -:左对齐
实例
# awk -F: '{printf "username:%-15s uid:%d\n",$1,$3}' /etc/passwd
操作符
算数操作符
+:加 -:减 *:乘 /:除 %:取余 ^:幂运算
字符串操作符:没有符号的操作符,字符串连接
赋值操作符
=:直接赋值 +=:相加后赋值给变量 -=:相减后赋值给变量 *=:相乘后赋值给变量 /=:相除后赋值给变量 ++:自加 --:自减
比较操作符
>:大于 <:小于 >=:大于等于 <=:小于等于 ==:等于 !=:不等于
模式匹配
~:匹配 !~:不匹配
逻辑操作符
&&:与 ||:或 !:非
函数调用
function_name(argu1,argu2,...)
实例
# awk 'BEGIN{print rand()}'
条件表达式
selector?if_true_expression:if_false_expression
实例
# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
PATTERN
-
empty:空模式,匹配每一行;
-
/regular expression/:仅处理能被此处模式匹配到的行,对模式取反在其之前加
!
; -
Relational Expression:关系表达式,结果有“真”有“假”,结果为“真”时才会被处理;
-
真:结果为非0值,非空字符串
-
line range:行范围
-
startline,stopline: /par1/,/par2/
-
注意:不支持直接给出数字格式
-
实例:
# awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
-
BEGIN/END模式
-
BEGIN{}:仅在开始处理文本前执行一次
-
END{}:仅在文本处理结束后执行一次
控制语句
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 }
注意:
-
多个语句之间需用分号分隔;
-
语句之间可实现嵌套,但是需用花括号进行约束;
-
单个语句时可省略花括号。
if-else
语法:
if(condition) statement [else {statement}]
使用场景:对awk取得的整行或某个字段做条件判断。
实例
# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
while
语法
while(condition) statement
使用场景:对一行内的多个字段逐一类似操作时使用,对数组中的各元素逐一处理时使用。
实例
# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /etc/grub2.cfg
for循环
语法
for(expr1;expr2;expr3) statement
实例
# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
特殊用法:能够遍历数组中的元素
for(var in array) {for-body}
break和continue
break:跳出循环
continue:提前结束本轮循环跳转到下一轮,即完成行中的字段间跳转
next:提前结束对本行的处理而直接进入下一行
实例
# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
array
关联数组:array[index-expression]
对于index-expression
需要注意:
-
可使用任意字符串,但是需要用双引号;
-
如果数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”。
实例
练习1:统计/etc/fstab文件中每个文件系统类型出现的次数; ~]# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab 练习2:统计指定文件中每个单词出现的次数; ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(j in count) {print j,count[j]}}' /etc/fstab
内置函数
数值处理
-
rand():返回0和1之间的一个随机数,但是一旦返回该值,再次请求时其值不再改变
字符串处理
-
length([s]):返回指定字符串的长度;
-
split(s,a[,r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中;
实例
# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'
原创文章,作者:Jeason,如若转载,请注明出处:http://www.178linux.com/58288