gawk入门及进阶
2017-05-23 20:18
225 查看
gawk入门及进阶
* 例5:统计文件中每个单词出现的次数:
]# awk -F: ‘{for(i=1;i<=NF;i++){words[$i]++}}END{for(i in words) {print i,words[i]}}’ /etc/passwd | sort -k 2 -nr
GNU awk 文本处理三工具: grep 、egrep、fgrep :文本过滤工具,pattern sed :行编辑器 模式空间 、保持空间 awk :报表生成器,格式化文本输出; AWK :Aho,Weinberger,Kernighan,三位作者,在Unix上使用 New AWK :NAWK gwak :GNU awk ,在Linux上使用 gawk : pattern scanning and processing language 基本用法 :gawk [option] 'program' FILE ... program :PATTERN{ACTION STATEMENTS} 语句之间用分号分隔 选项: -F :指明输入时用到的字段分隔符; -v var=value :自定义变量; 1. print print item1,item2,... 要点: (1) 逗号作为分隔符,默认输出结果的分隔符是一个空白字符; (2) 输出的各item可以是字符串,也可以是数值,当前记录的字段、变量或awk的表达式; (3) 如省略item,相当于print $0,即输出全部; 2. 变量:【注意】引用变量不要加$符号 2.1 内建变量 FS :input field seperator,默认为空白字符; OFS :output field seperator,默认为空白字符; 如:]# awk -v FS=':' -v OFS=',' '{print $1,$2}' /etc/passwd ]# awk -v RS=':' '{print}' /etc/passwd RS :input record seperator,输入时的换行符; ORS :output record seperator,输出时的换行符; 如:]# awk -v RS=':' -v ORS=' ' '{print}' /etc/passwd root x 0 0 root /root /bin/bash bin x 1 1 bin /bin /sbin/nologin NF :number of field,字段数量 如:]# awk -v OFS='********' '{print NF,$NF,$0}' 【注意】引用变量不要加$符号: 此处{print NF}与{print $NF} 二者的输出效果不同,NF代表本行有多少个字段,$NF代表将NF的值作为变量名。 最终的执行效果为:输出本行的字段数量和本行最后一个字段。 NR :number record , 处理的行数,如果有多个文件则一起计数 FNR:file number recor ,多个文件分别计数 例1 :输出处理两个文件的行数,两个文件行数一起计算 ]# awk '{print NR}' /etc/fstab /etc/issue 例2 :输出处理两个文件的行数,两个文件行数单独分别计算 ]# awk '{print FNR}' /etc/fstab /etc/issue FILENAME : 当前处理的文件的文件名 例1 :]# awk '{print FNR,FILENAME}' /etc/fstab /etc/issue ARGC :命令行参数的个数; ARGV :数组,保存的是命令行所给定的各参数; 如: ]# awk 'BEGIN{print ARGC}' /etc/fstab /etc/issue 3 ]# awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/issue awk ]# awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/issue /etc/fstab ]# awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/issue /etc/issue 2.2 自定义变量 【注意】引用变量不要加$符号 (1) -v var=value 变量名区分字符大小写: 如:]# awk -v test="hello awk" 'BEGIN{print test}' hello awk (2) 在program中直接定义 如:]# awk 'BEGIN{test="hello awk";print test}' hello awk 3. printf 命令 格式化输出 :printf FORMAT,item1,item2,... (1) FORMAT必须给出; (2) 不会自动换行,需要显式给出换行控制符,\n (3) FORMAT中需要分别为后面的每个item指定一个格式化符号; 格式符: %c :显示字符的ASCII码 %d,%i:显示十进制整数 %e,%E :科学计数法数值显示 %f :显示为浮点数 %g,%G : 以科学计数法或浮点形式显示数值 %s :显示字符串 %u :无符号整数 %% :显示%自身 如:]# awk -F: '{printf "Username: %s---UID:%d\n",$1,$3}' /etc/passwd Username: root---UID:0 Username: bin---UID:1 修饰符:在格式符前面加修饰的符号,控制格式的显示机制 #[.#]:第一个数字控制显示的宽度(默认右对齐):第二个#标识小数点后的精度(可省略) %3.1f 如: ]# awk -F: '{printf "Username:%10s UUID:%7.1f\n",$1,$3}' /etc/passwd Username: ntp UUID: 38.0 Username: abrt UUID: 173.0 - :代表左对齐 如: ]# awk -F: '{printf "Username: %-10sUUID: %5.1f\n",$1,$3}' /etc/passwd Username: ntp UUID: 38.0 Username: abrt UUID: 173.0 + :显示数值的正负符号 4. 操作符 算术操作符: x+y,x-y,x*y,x/y,x^y,x%y : -x :单目操作符,变为负数 +x :转换为数值 字符串操作符:没有符号的操作符表示字符串连接 赋值操作符: =,+=,-=,*=,/=,^=,%= ++,-- :自加,自减 比较操作符: >,>=,<,<=,!=,== 模式匹配符: ~ :匹配 !~ :是否不匹配 逻辑操作符: && || ! 函数调用: function_name(arg1,arg2,...) 条件表达式: selector?if-true-expression:if-false-expression 两个expression间用冒号:分隔 例如:]# awk -F':' '{$3>499?usertype="common user":usertype="sys user";printf "%-10s %5d %s\n",$1,$3,usertype}' /etc/passwd 5. pattern (1) empty :空模式,匹配每一行 (2) /regular expression/ :仅对能被此处模式匹配到的行 如:]# awk '/nologin$/{print NR,$0}' /etc/passwd 2 bin:x:1:1:bin:/bin:/sbin/nologin 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin 【注意】此处不能print $1 。 (3) relational expression :关系表达式,结果为布尔型值,即真和假;结果为真才能被匹配处理; 真:结果为非0值,非空字符串 假:结果为0,空字符串 例1: ]# awk -F: '$3>499{printf "username:%-10s UID:%3d\n",$1,$3}' /etc/passwd username:achuDk UID:500 username:gentoo UID:501 例2: ]# awk -F: '$NF~/bash$/{printf "linenum:%-3d username:%-6s bash:%d\n",NR,$1,$NF}' /etc/passwd linenum:1 username:root bash:0 linenum:20 username:achuDk bash:0 (4) line ranges :行范围 startline,endline : /pat1/,/pat2/ 【注意】不支持直接给出数字的格式 例如: ]# awk -F: '/^r/,/^h/{SUM=$3+$4;printf "Line record: %-2d Uname: %10s UID: %3d GID: %3d $3+$4: %3d\n",NR,$1,$3,$4,SUM}' /etc/passwd Line record: 4 Uname: adm UID: 3 GID: 4 $3+$4: 7 Line record: 5 Uname: lp UID: 4 GID: 7 $3+$4: 11 例如: ]# awk -F: 'NR>=3&&NR<=10{print}' /etc/passwd daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin (5) BEGIN/END 模式: BEGIN{} :仅在开始处理文件中的文本之前执行一次,如:输出表头 END{} :仅在文本处理完成之后,命令结束之前执行一次; (6) 常用的action 1) Expression 2) Control statements : 控制语句:if,while等; 3) Compound statements : 组合语句; 4) input statements :输入语句 5) output statements :输出语句 (7) Control statements 控制语句 if(condition) {statements} if(condition) {statements} else {statements} while(condition) {statements} do {statements} while(condition) for(expr1;expr2;expr3) {statements} break continue delete array[index] delete array exit { statements } 7.1 if-else 使用场景:对awk取得的整行或某个字段做条件判断; 语法: 单分支:'{if(condition) statement}' 多分支:'{if(condition) {statement} else {statement}}' 例1:找出/etc/passwd目录下UID<=100的用户打印Uname和UID: 18a1b 单分支语句示例: ]# awk -F: '{if($3<=10)print $1,$3}' /etc/passwd 多分支语句示例: 例1:]# awk -F: '{if($3<=499){printf "Super user: %s\n",$1}else{printf "Common user: %s\n",$1}}' /etc/passwd 例2:]# awk -F: '{if($NF=="/bin/bash") {print NR,$1}else {print $1,$NF}}' /etc/passwd 如:显示磁盘空间利用率大于2%的磁盘 ]# df | awk '/^\/dev/{print $1,$6}' | awk -F% '{print $1}' | awk '{if($2>=2) printf "The used-percent of this partition has over %%2:%s \n",$1}' The used-percent of this partition has over %2:/dev/sda2 The used-percent of this partition has over %2:/dev/sda1 7.2 while 循环 语法:while(conditiont) statement 条件为“真”,进入循环;条件为“假”,退出循环; 使用场景:对【一行内的多个字段】或对【数组中的各元素】逐一进行类似处理时使用,因为awk已经对整个文件的所有行进行循环; 示例:显示某文件中所有符合条件的行,对行内的每一个字段,显示字段本身和字段内字符的个数: lenth(WORDS_NAME) :长度函数,显示某字段内字符的个数 结果:]# awk '/^[[:space:]]+kernel/{i=1;while(i<=NF) {print $i,length($i);i++}}' /etc/grub.conf kernel 6 /vmlinuz-2.6.32-642.el6.x86_64 30 ro 2 root=UUID=aadac335-a5b8-40ef-bdbe-ecb0fcc09d01 46 rd_NO_LUKS 10 rd_NO_LVM 9 LANG=en_US.UTF-8 16 rd_NO_MD 8 SYSFONT=latarcyrheb-sun16 25 crashkernel=auto 16 KEYBOARDTYPE=pc 15 KEYTABLE=us 11 rd_NO_DM 8 扩展条件:设定条件:仅显示length($i)>=6的字段 ]# awk '/^[[:space:]]+kernel/{i=1;while(i<=NF) {if(length($i)>=6) {print $i,length($i)};i++}}' /etc/grub.conf kernel 6 /vmlinuz-2.6.32-642.el6.x86_64 30 7.3 do-while循环 语法:do statemnet while(condition) 意义:至少执行一次循环体,即使condition为假 7.4 for循环 语法:for(expr1;expr2;expr3) statement expr1 :控制变量初始化 expr2 :条件判断 expr3 :控制变量修正表达式 for-body :循环体 for(variable assignment;condition;iteration process) {for-body} 示例:显示某文件中所有符合条件的行,对行内的每一个字段,显示字段本身和字段内字符的个数:使用length()函数。 结果:]# awk '/^[[:space:]]+kernel/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub.conf 特殊用法: 能够遍历数组中的元素: 语法:for(var in array) {for-body} 7.5 switch语句 类似于bash中的case语句 语法:swtich(expression) {case VALUE1 or /REGEXP1/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement} 7.6 break和continue 仅针对某一行内多个字段间的循环进行处理 break :跳出第n层循环 continue :提前结束本轮循环 7.7 next 提前结束对本行的处理,直接进入下一行的处理 示例:跳过UID号为奇数的行,仅显示UID号为偶数的用户 结果:]# awk -F: '{if($3%2!=0) {next} else {print $1,$3}}' /etc/passwd root 0 daemon 2 8. array 数组 关联数组 :array[index-expression] index-expression 类型 (1) 可使用任意字符串: (2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”; 【注意】 1、可使用任意字符串,字符串要使用双引号; 2、如果想判断数组中是否存在某元素或某元素是否为空时,要使用“index in array”格式进行,千万不要通过引用这个元素来判断 weekdays["mon"]="Monday" 例如: ]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"],weekdays["tue"]}' Monday Tuesday 要遍历数组中的每个元素,要使用for循环; for(var in array) {for-body} 例1: ]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}' Monday Tuesday 【注意】var会遍历array的每个索引; 例2:统计tcp协议的所有端口的连接状态: ]# netstat -tnl | awk '{print $4,$0}' | awk '/^[[:digit:]]+/{state[$NF]++}END{for(i in state) {print i,state[i]}}' LISTEN 3 例3:统计所有进程中以root身份运行的进程 ]# ps aux | awk '{user[$1]++}END{for(i in user);{print i,user[i]}}' root 141 例4:统计/etc/fstab中所有fs出现的频率分布 ]# cat /etc/fstab | awk '/^[[:alnum:]]/{fstype[$3]++}END{for(i in fstype) {printf "fs-type: %-10s distribution: %d \n",i,fstype[i]}}' fs-type: devpts distribution: 1 fs-type: swap distribution: 1 fs-type: sysfs distribution: 1 fs-type: proc distribution: 1 fs-type: tmpfs distribution: 1 fs-type: ext4 distribution: 4
* 例5:统计文件中每个单词出现的次数:
]# awk -F: ‘{for(i=1;i<=NF;i++){words[$i]++}}END{for(i in words) {print i,words[i]}}’ /etc/passwd | sort -k 2 -nr
]# awk '{for(i=1;i<=NF;i++){fstype[$i]++}}END{for(i in fstype) {print i,fstype[i]}}' /etc/fstab 9. 函数 9.1 内置函数 rand() :返回0和1之间的随机数 如:]# awk 'BEGIN{print rand()}' 0.237788 【注意】只有第一次取是随机的,以后都会成为定值 字符串处理: length([s]) :返回指定字符串的长度 sub(r,s,[t]) :以r表示的模式来查找t所表示的字符串中的匹配的内容,并将其第一次出现替 换为s所表示的内容;t可以省略 gsub(r,s,[t]) :全局替换 split(s,a[,r]) :以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中;r可以省略 例如:统计netstat信息中的local address 去除端口号的数据: ]# netstat -tnl | awk '/^tcp/{split($4,ip,":");count[ip[1]]++}END{for(i in count) {print i,count[i]}}' 3 127.0.0.1 1 0.0.0.0 2
相关文章推荐
- [译]Kinect for Windows SDK开发入门(十五):进阶指引 下
- 精选在线课程:前端开发入门、进阶与实战(中文系列)
- Kubernetes 1.3 从入门到进阶 安装篇(2)
- C++入门进阶之6: 多态性
- 推荐算法从入门、进阶到高级
- 简明 Vim 练级攻略(Vim新手入门,进阶必读)by-陈皓
- SQL Server 扩展事件(Extented Events)从入门到进阶(4)——扩展事件引擎——基本概念
- react入门到进阶(二)
- sbt入门与进阶
- ASP编程入门进阶(十八):FSO组件之文件操作(下)
- ASP编程入门进阶(三):接触脚本程序
- [Python入门及进阶笔记]Python-魔术方法小结(方法运算符重载)
- ASP编程入门进阶(十七):FSO组件之文件夹操作
- C++入门进阶之6: 多态性
- 零基础 JNI 入门 + 进阶
- J2EE核心:iBatis DAO入门与进阶一
- [.net 面向对象程序设计进阶] (2) 正则表达式 (一) 快速入门
- 13个Tensorflow实践案例,教你入门到进阶
- 各类工程师入门进阶的路线图
- 【Ogre编程入门与进阶】第十三章 公告板与粒子系统