三剑客之gawk
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了三剑客之gawk相关的知识,希望对你有一定的参考价值。
gawk:
- gawk - pattern scanning and processing language: 模块扫描及处理语言
- AWK: Aho,Weinberger,Kernighan 三个设计人名字
- GNU awk :gawk
- awk :功能遍历文件每一行并且对每一行做单独处理.
- awk也称报告生成器,格式化文本输出工具
- 基本用法 :
- gawk [options] `program` FILE..
- program:PATTERN{ACTTION STATEMENTS}动作语句
- 语句之间用分号分隔
- 选项:
- -F:指明输入时用到的字段分隔符;
- [[email protected] ~]# awk -F : ‘{print $1,$2}‘ /etc/passwd
- root x
- bin x
- -v var=value :自定义变量;
-
print:
- print item1, item2,...
- [[email protected] ~]# awk ‘{print $1,$2}‘ /etc/passwd
- root:x:0:0:root:/root:/bin/bash
- bin:x:1:1:bin:/bin:/sbin/nologin
- 要点:
- 1 . 逗号分隔;
- 2 . 输出的各item可以字符串,也可以是数值;当前记录的字段,变量或awk的表达式;
- [[email protected] ~]# awk -F : ‘{print "username:"$1,$2}‘ /etc/passwd
- username:root x
- username:bin x
- 在awk中变量不适用引号 ,否则会被当做字符串输出
- [[email protected] ~]# awk -F : ‘{print "username:$1"}‘ /etc/passwd
- username:$1
- username:$1
- 如省略item,相当于print $0;
- [[email protected] ~]# awk -F : ‘{print}‘ /etc/passwd
- root:x:0:0:root:/root:/bin/bash
- bin:x:1:1:bin:/bin:/sbin/nologin
- 变量
- 2.1 内键变量
- FS:input field seperator,默认为空白字符;
- 指明以什么分隔
- [[email protected] ~]# awk -v FS=‘:‘ ‘{print $1}‘ /etc/passwd
- root
- bin
- 相当于 -F
- OFS:output field seperator, 默认为空白字符
- 自定义分隔符:
- [[email protected] ~]# awk -v FS=‘:‘ -v OFS=‘:‘ ‘{print $1,$3}‘ /etc/passwd
- root:0
- bin:1
- 每一个-v用来定义一个变量
- RS input record seperator,指明输入时的换行符
- 以空白为换行符
- [[email protected] ~]# awk -v RS=‘ ‘ ‘{print}‘ /etc/passwd
- ORS output record seperaor, 指明输出时的换行符
- 指明#号为输出换行符
- [[email protected] ~]# awk -v RS=‘ ‘ -v ORS=‘#‘ ‘{print}‘ /etc/passwd
- NF :number of field ,字段数量
- [[email protected] ~]# awk ‘{print NF}‘ /etc/fstab
- 0
- 1
- 2
- 10
- awk 引用内部变量时不需要使用$
- {print NF} , {print $NF}
- NR :number of record 文件的行数,对行进行统计
- [[email protected] ~]# awk ‘{print NR}‘ /etc/fstab
- 1
- 2
- 3
- FNR :各文件分别计数;行数
- awk ‘{print FNR}‘ /etc/fstab /etc/passwd
- FILENAME : 当前文件名
- [[email protected] ~]# awk ‘{print FILENAME}‘ /etc/fstab
- /etc/fstab
- etc/fstab
- ARGC:命令行参数的个数
- [[email protected] ~]# awk ‘BEGIN{print ARGC}‘ /etc/fstab
- 2
- ARGV:数组,保存的是命令行所给定的各参数;
- [[email protected] ~]# awk ‘BEGIN{print ARGV[0]}‘ /etc/fstab
- awk
-
自定义变量
- 1 -v var=value
- 变量名区分字符大小写;
- awk -v aa="bb" ‘BEGIN{ PRINT aa}‘
- [[email protected] ~]# awk -v aa="bb" ‘{print aa}‘ /etc/passwd
- bb
- bb
- 2 在program中直接定义
- [[email protected] ~]# awk ‘BEGIN{aa="bb";print aa}‘
- bb
-
printf命令
- 格式化输出: printf FORMAT格式符, itrm1,item2,....
- 1 . FORMAT 必须给出;
- 2 . 不会自动换行,需要显示给出换行控制符,\n
- 3 . FORMAT中需要分别尾喉面的每个item指定一个格式化符号;
- 格式符:任何格式符后所对应的条目会被套在格式符上显示item不会单独显示
- %c :显示字符的ASCII码;
- %d,%i:显示十进制整数;
- %e,%E: 科学计数法数值显示;
- %f; 显示为浮点数
- %g,%G:以科学计数法或浮点形式显示数值;
- %s:显示字符串
- %u:无符号整数
- %%: 显示%自身:
- 默认不会显示换行符
- 示例
- [[email protected] ~]# awk -F: ‘{printf "username:%s\n",$1}‘ /etc/passwd
- username:root
- username:bin
- username:daemon
- [[email protected] ~]# awk -F: ‘{printf "username:%s,UID: %d\n",$1,$3}‘ /etc/passwd
- username:root,UID: 0
- username:bin,UID: 1
- username:daemon,UID: 2
- 修饰符:
- #[.#]:第一个数字控制显示的宽度,第二个#表示小数点后的精度;
- %3.1f
- -:左对齐
- +:显示数值的符号
- 右对齐:
- [[email protected] ~]# awk -F: ‘{printf "username:%15s,UID: %d\n",$1,$3}‘ /etc/passwd
- username: root,UID: 0
- username: bin,UID: 1
- username: daemon,UID: 2
- 左对齐:
- [[email protected] ~]# awk -F: ‘{printf "username:%-15s:UID: %d\n",$1,$3}‘ /etc/passwd
- username:root :UID: 0
- username:bin :UID: 1
- username:daemon :UID: 2
- username:adm :UID: 3
- 操作符
- 算数操作符
- x+y, x-y,x*y,x/y,x^y,x%y
- -x
- +x:把一个字符串转换为数值
- 字符串操作符: 没有符号的操作符,字符串连接
- 赋值操作符:
- =,+=,-=, *=,/=, %=, ^= ,++ ,--
- 比较操作符:
- >, >=,<, <=, !=,==
- 模式匹配符:
- &&
- ||
- !
- 函数调用:
- function_name(argue1 ....)
-
条件表达式:
- selector?if-ture-expression:if-false-expression
- 示例:
- 找出/etc/passwd/ 系统用户和普通用户
- [[email protected] ~]# awk -F: ‘{$3 >=900?Utype="common user":Utype="sysuser ro dime"; printf "%15s:%-s\n",$1,Utype,$3}‘ /etc/passwd
- root:sysuser ro dime
- bin:sysuser ro dime
- daemon:sysuser ro dime
- adm:sysuser ro dime
- lp:sysuser ro dime
-
pattern
- 1 empty:空模式 , 匹配每一行;
- 2 /regular expression/:仅处理能够被此处的模式匹配到的行
- [[email protected] ~]# awk ‘/UUID/{print $1}‘ /etc/fstab
- UUID=ab5839fc-cf8d-48ad-9067-49385b8645ca
- UUID=aac33902-12f8-4adb-b680-d96dab832d30
- UUID=b6781c5f-6bb6-4add-b181-5b664db4c358
- UUID=b272d4c8-df03-4e0c-95f9-5aa3c83443ee
- [[email protected] ~]# awk ‘!/UUID/{print $1}‘ /etc/fstab
- #
- #
- #
- #
- #
- #
- #
- 3 relational expression ;关系表达式,结果有"真" 有"假" :结果为"真"才会被处理;
- 真:结果为非0值,非空字符串;
- 显示/etc/passwd中uid大于等于500的用户或这说普通用户
- [[email protected] ~]# awk -F: ‘$3>=500{print $1,$3}‘ /etc/passwd
- nfsnobody 65534
- user 500
- logstash 501
- 显示/etc/passwd中以/bin/bash结尾用户名和的行
- awk -F: ‘$NF~"/bin/bash"{print $1,$NF}‘ /etc/passwd
- [[email protected] ~]# awk -F: ‘$NF=="/bin/bash"{print $1,$NF}‘ /etc/passwd
- root /bin/bash
- user /bin/bash
- logstash /bin/bash
-
line ranges:行范围
- startline, endline: /pat1,/pat2/
- 对/etc/passwd中第十行到二十行处理
- [[email protected] ~]# awk -F: ‘10,20{print $1}‘ /etc/passwd
- root
- bin
- daemon
- 注意: 不支持直接给出数字的格式
- [[email protected] ~]# awk -F: ‘(NR>=2&&NR<=10){print $1} ‘ /etc/passwd
- bin
- daemon
- adm
- lp
-
BEGIN/END模式
- NEGIN{} :仅在开始处理文件中的文本之前执行一次;
- END{} :紧在文本处理完成之后执行一次;
- [[email protected] ~]# awk -F: ‘BEGIN{print" username usid \n------------"} {print $1,$2}‘ /etc/passwd
- username usid
- ------------
- root x
- bin x
- daemon x
- [[email protected] ~]# awk -F: ‘BEGIN{print" username usid \n------------"} {print $1,$2}END{print "***********" }‘ /etc/passwd
-
常用的action
- 1 . Expressions 表达式
- 2 . Control statements : if while 等;条件控制语句
- 3 . Compound statements: 组合语句;
- 4 . input statements :输入语句
- 5 . output statements :输出语句
-
控制语句
- if(condition) {statements}但分支if语句
- if (condition) {statements} else {statments} 双分支if语句
- while (condition) {statements}
- do {staements} while (condition) 无论条件真假都会执行一次
- for (expr1;expr2;expr3) {statements}
- break
- continue
-
if else
- 语法:if (condition)statement [else statement]如果只有多个语句需要加花括号
- 使用场景:对awk取得的正行或某个字段做条件判断
- 找出 /etc/passwd 中系统用户和普通用户
- [[email protected] ~]# awk -F: ‘{if($3>=500) print $1,$3}‘ /etc/passwd
- nfsnobody 65534
- user 500
- logstash 501
- [[email protected] ~]# awk -F: ‘{if($3<=500){printf "sysuser:%15s\n",$1}else{printf "common user: %15s\n",$1}}‘ /etc/passwd
- sysuser: root
- sysuser: bin
- 显示/etc/passwd中以/bin/bash结尾用户名,及shell.
- [[email protected] ~]# awk -F: ‘{if($NF=="/bin/bash")print $1,$7‘ /etc/passwd
- root
- user
- logstash
- 如果某一行的字段数大于五个则显示否则不显示
- [[email protected] ~]# awk ‘{if(NF>5)print }‘ /etc/fstab
- # Created by anaconda on Tue Apr 25 23:44:59 2017
- # Accessible filesystems, by reference, are maintained
- 查看dev设备使用率大于%20的显示出来
- [[email protected] ~]# df -h | awk -F[%] ‘/^\/dev/{print $1}‘|awk ‘{if($NF>=5)print $NF}‘
- 8
-
while循环
- 语法: while(condition) statement
- 条件"真",进入循环:条件"假"退出循环
- 使用场景: 对一行内的多个字段逐一类似处理时使用:对数组中的个元素逐一处理时使用:
- 示例
- 对/etc/grub.conf/initrd开头行做字段字符个数统计
- [[email protected] test]# awk ‘/^[[:space:]]*initrd/{i=1;while(i<=NF) {print $i,length($i); i++}}‘ /etc/grub.conf
- initrd 6
- /initramfs-2.6.32-642.el6.x86_64.img 36
- 对/etc/grub.conf/initrd开头行做字段字符个数统计,并只显示字段大于等于4的行
- [[email protected] ~]# awk ‘/^[[:space:]]*initrd/{i=1;while(i<=NF) {if(length($i)>=4) print $i,length($i); i++}}‘ /etc/grub.conf
- initrd 6
- /initramfs-2.6.32-642.el6.x86_64.img 36
-
for循环
- 语法 :for(expr1;expr2;expr3...) statement()
- for(variable assignment; condition;iteration process) {for-body}
- 示例:
- 对/etc/grub.conf/initrd开头行做字段字符个数统计,并只显示字段大于8的行
- [[email protected] ~]# awk ‘/^[[:space:]]*initrd/{for(i=1;i<=NF;i++) {if(length($i)>8) print $i,length($i)}}‘ /etc/grub.conf
- /initramfs-2.6.32-642.el6.x86_64.img 36
- 特殊用法:
- 能够遍历数组中的元素;
- 语法:for(var in array) {for-body}
-
next :
- 控制awk提前结束本行的处理而直接进入下一行
- 打印出/etc/passwd中ID为偶数的用户
- [[email protected] test]# awk -F: ‘{if($3%2!=0) next; print $1,$3}‘ /etc/passwd
- root 0
- daemon 2
- lp 4
- 分析 如果用第三列%2后不等于0 则直接跳过 打印 第一列 和第三列
-
array
-
关联数组
- array [index-expression]
- index-expression
- 1 . 可使用任意字符串;字符串要是用双引号
- 2 . 如果某数组元素实现不存在,在引用时,awk会自动创建元素,并将其值初始化为"空串"
- 要判断数组中是否存在某元素,要是用"index in array"格式进行;
- weekdays[mon]=Monday\
- [[email protected] test]# awk ‘BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}‘
- Monday
- 若要遍历数组中的每个元素,要是用for循环
- [[email protected] test]# awk ‘BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays){print weekdays[i]}}‘
- Monday
- Tuesday
- 注意:var会遍历array的每个索引;
- 统计ss -tan每一种状态个出现多少次
- [email protected] test]# netstat -tan|awk ‘/^tcp\>/{state[$NF]++}END{for(i in state) {print i,state[i]}}‘
- ESTABLISHED 1
- LISTEN 9
- 统计http日志文件每个用户访问的次数
- [[email protected] test]# awk ‘{ip[$1]++}END{for(i in ip) {print i,ip[i]}}‘ /var/log/httpd/access_log
- 192.168.174.1 17
- 练习:
- 1 . 统计 /etc/fstab 文件中每个文件系统类型出现的次数;
- [[email protected] test]# awk ‘ /^UUID/{fs[$3]++}END{for (i in fs) {print i,fs[i]}}‘ /etc/fstab
- swap 1
- ext4 3
- 2 . 统计指定文件中每个单词出现的次数
- [[email protected] ~]# awk ‘ {for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}‘ /etc/fstab /etc/fstab
- mount(8) 2
- Accessible 2
-
函数
- 内置函数
- 数值处理:
- rand() :返回0和1之间一个随机数;
- [[email protected] ~]# awk ‘BEGIN{print rand()}‘
- 0.237788
- 只有第一次取的是随机值
- 字符串处理:
- length([s]): 返回指定字符串的长度;
- sub (r,s,[t]): 以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;
- gsub (r,s,[t]) :表示全局替换
- split(s,a[,r]):以r为分隔符切割字符s,并将切割后的结果保存至a所在数组中
以上是关于三剑客之gawk的主要内容,如果未能解决你的问题,请参考以下文章