简介
AWK是一种优良的文本处理工具。它不仅是 Linux 中也是任何环境中现有的功能最强大的数据处理引擎之一。AWK 提供了极其强大的功能:可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上 AWK 的确拥有自己的语言:AWK 程序设计语言, 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。最简单地说, AWK 是一种用于处理文本的编程语言工具。
awk经过改进生成的新的版本nawk,gawk,现在默认linux系统下日常使用的是gawk,用命令可以查看正在应用的awk的来源(ls -l /bin/awk )
awk
gawk – pattern scanning and processing language
基本用法
awk [options] 'program' file1,file2,…..
options常用选项:
-F[]:指定分隔符,使用[]可以指定多个分隔符
-v var=varl:自定义变量
program组成:
PATTERN {ACTION STATEMENT},由语句组成,语句分隔符是";"
ACTION:print,printf
1 print 常用输出命令
用法:print item1, item2, …
要点:
(1) 逗号分隔符;
(2) 输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式;
(3) 如省略item,相当于print $0;
注意:
BEGIN
有时候可能在处理数据前运行脚本,比如为报告创建开头部分,BEGIN关键字就是用来做这个的,它会强制gawk在读取数据前执行BEGIN关键字后制指定的程序脚本.
END
跟BEGIN关键字类似,END关键字允许你指定一个程序脚本,gawk会在读完数据后执行它的.
示例1:awk程序读取文本文件并显示第1数据字段值
awk '{print $1}' test5.txt
示例2:显示出/etc/fstab 文件里面的第2段和第4段数据,开头加个hello
tail -5 /etc/fstab | awk '{print "hello",$2,$4}'
2.变量
2.1 内建变量
FS:input field seperator,默认为空白字符; OFS:output field seperator,默认为空白字符; RS:input record seperator,输入时的换行符; ORS:output record seperator,输出时的换行符; NF:number of field,字段数量 {print NF}, {print $NF} NR:number of record, 行数; FNR:各文件分别计数;行数; FILENAME:当前文件名; ARGC:命令行参数的个数; ARGV:数组,保存的是命令行所给定的各参数;
2.2 自定义变量
(1) -v var=value
变量名区分字符大小写;
(2) 在program中直接定义
示例3:给test4这个文件用awk 处理之前设置一个开头部分,处理完成后设置一个结尾部分.
awk 'BEGIN{print "This is the beginning";print "userid shell";print "—— ——";FS=":"}''{print $1,$7}'END'{print "Here is the end"}' test4.txt
示例4 以冒号为字段分隔符显示/etc/passwd文件里面的第1字段
awk -v FS=":" '{print $1}' /etc/passwd
示例5:处理后显示出test6.txt的第1,2,3数据字段值
awk 'BEGIN{FS="."}{print $1,$2,$3}' test6.txt
示例6: 通过设置OFS变量,你可以在输出中使用任意字符来分割字段
awk 'BEGIN{FS=".";OFS="-"}{print $1,$2,$3}' test6.txt
awk -v FS="." -v OFS="-" '{print $1,$2,$3}' test6.txt 这种写法也可以
示例7: 显示出/etc/passwd 第1段,第3段和第7段,并且以冒号字段分隔符显示出来
awk -v FS=":" -v OFS=":" '{print $1,$3,$7}'
示例8:以空白为换行符, 以#号为数据行为分隔符显示出/etc/passwd
awk -v RS=' ' -v ORS='#' '{print}' /etc/passwd
示例9:显示/etc/fstab 每一行多少字段
awk '{print NF}' /etc/fstab
示例10:显示/etc/fstab 最后一个字段
awk '{print $NF}' /etc/fstab
示例11:统计/etc/fstab行数对行直接编号
awk '{print NR}' /etc/fstab
示例12:对/etc/fstab /etc/issue 各文件分别计数,行数
awk '{print FNR}' /etc/fstab /etc/issue
示例13:显示命令行参数的个数
awk 'BEGIN{print ARGC}' /etc/fstab /etc/issue
示例14:显示命令行参数数组的第3个参数
awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/issue
3 printf命令
格式化输出:printf FORMAT, item1, item2, …
(1) FORMAT必须给出;
(2) 不会自动换行,需要显式给出换行控制符,\n
(3) FORMAT中需要分别为后面的每个item指定一个格式化符号;
格式符:
%c: 显示字符的ASCII码; %d, %i: 显示十进制整数; %e, %E: 科学计数法数值显示; %f:显示为浮点数; %g, %G:以科学计数法或浮点形式显示数值; %s:显示字符串; %u:无符号整数; %%: 显示%自身;
修饰符:
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度;
%3.1f
-: 左对齐
+:显示数值的符号
示例15:显示/etc/passwd 文件中的第一字段,格式化输出。
awk -F: '{printf "%s\n",$1}' /etc/passwd
示例16:显示/etc/passwd 文件中的第1和第3个字段,第1段格式化字符串,第三段格式化十进制整数并且第3段前面要显示UID:
awk -F: '{printf "%s, UID:%d\n",$1,$3}' /etc/passwd
示例17:显示/etc/passwd 文件中的第1和第三个字段,第1段格式化字符串并且左对齐,第三段格式化十进制整数并且第3段前面要显示UID:
awk -F: '{printf "%-15s UID:%d\n",$1,$3}' /etc/passwd
4.操作符
算术操作符: x+y, x-y, x*y, x/y, x^y, x%y -x +x: 转换为数值; 字符串操作符:没有符号的操作符,字符串连接 赋值操作符: =, +=, -=, *=, /=, %=, ^= ++, -- 比较操作符: >, >=, <, <=, !=, == 模式匹配符: ~:是否匹配 !~:是否不匹配 逻辑操作符: && || ! 函数调用: function_name(argu1, argu2, ...) 条件表达式: selector?if-true-expression:if-false-expression
示例18:以冒号为字段分隔符,判断/etc/passwd 文件中的第三个字段,大于500的为显示为普通用户,否则其他的显示为管理员或者是系统用户。
awk -F: '{$3>=500?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
示例19:以冒号为字段分隔符,找出/etc/passwd 文件中第1个字段为root显示出来
awk -F":" '$1=="root"{print $1}' /etc/passwd
5 PATTERN
(1) empty:空模式,匹配每一行;
(2) /regular expression/:仅处理能够被此处的模式匹配到的行;
(3) relational expression: 关系表达式;结果有“真”有“假”;结果为“真”才会被处理;
真:结果为非0值,非空字符串;
(4) line ranges:行范围,
startline,endline:/pat1/,/pat2/
注意: 不支持直接给出数字的格式
(5) BEGIN/END模式
BEGIN{}: 仅在开始处理文件中的文本之前执行一次;
END{}:仅在文本处理完成之后执行一次;
示例20:匹配/etc/passw文件中结尾是bash的,显示出第1段和最后一段
awk -F":" '$NF~/bash$/{print $1,$NF}' /etc/passwd
示例21:显示出test8.txt文件中root开头一直到myuser10结尾的行
awk -F":" '/^root/,/^myuser10/{print $1}' test8.txt
示例22:匹配/etc/passwd文件中行号大于等于2和小于等于10,显示出第1个字段
awk -F":" '(NR>=2&&NR<=10){print $1}' /etc/passwd
6.控制语句
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 }
6.1 if-else
语法:if(condition) statement [else statement]
示例23:判断如果ID号大于等于500 显示出来是普通用户 否则就是管理员或者系统用户
awk -F: '{if($3>=500) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
示例24:磁盘使用比率大于%10就显示出来
df -h | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>=10) print $1}'
6.2 while循环
语法:while(condition) statement
条件“真”,进入循环;条件“假”,退出循环;
示例25:显示boot/grub/grub.conf 文件中以空格开头kernel哪一行字段内容和字符的个数
awk '/^[[:space:]]*kernel/{i=1;while(i<=NF) {print $i,length($i); i++}}' /boot/grub/grub.conf
示例26:显示boot/grub/grub.conf 文件中以空格开头kernel哪一行字段内容和字符的个数,字符数大于8的才显示
awk '/^[[:space:]]*kernel/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /boot/grub/grub.conf
6.3 for循环
语法:for(expr1;expr2;expr3) statement
for(variable assignment;condition;iteration process) {for-body}
示例27:显示boot/grub/grub.conf 文件中以空格开头kernel哪一行字段内容和字符的个数(用for循环)
awk '/^[[:space:]]*kernel/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /boot/grub/grub.conf
6.4 next
提前结束对本行的处理而直接进入下一行;
示例28:显示用户id 号为偶数的用户
awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
7.array
关联数组:array[index-expression]
index-expression:
(1) 可使用任意字符串;字符串要使用双引号;
(2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”;
若要判断数组中是否存在某元素,要使用"index in array"格式进行;
示例29:weekdays赋值第一个元素Monday,第二个元素Tuesday,并打印出第一个元素
awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["tue"]}'
若要遍历数组中的每个元素,要使用for循环
示例30:weekdays赋值第一个元素Monday,第二个元素Tuesday,并且都打印出来
awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
示例31:netstat -tan 统计tcp状态出现了多少次
netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) { print i,state[i]}}'
示例32:统计/var/log/httpd/access_log 文件中每个IP访问多少次
awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
8.函数
8.1 内置函数
数值处理:
rand():返回0和1之间一个随机数;
字符串处理:
length([s]):返回指定字符串的长度;
sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;
gsub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现均替换为s所表示的内容;
split(s,a[,r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中;
原创文章,作者:liangkai,如若转载,请注明出处:http://www.178linux.com/12129