awk 是一个报告生成器 , 文本编辑器 , 同时自身也是一种编程语言 ,它支持条件判断、数组、循环等功能
功能 : 对文本数据进行汇总处理 , 对数据进行排版 .
注 : awk只能对读入到内存中的信息进行处理 , 无法对内容所在的原文件内容进行修改 , 想要修改原文件内容可以使用sed命令来改
grep 、sed、awk被称为linux中的"三剑客" , 相对这三者来说 : grep 更适合单纯的查找或匹配文本 ;sed 更适合编辑匹配到的文本 ;awk 更适合对文本进行较复杂格式处理
grep , sed 以及跟多的Linux 的 bash 用法可参考上篇博客 : https://blog.51cto.com/14181896/2359243
一 .awk语法格式及基本使用
语法一 : awk [选项] '/匹配模式/{处理动作1 , 处理动作2...}' 文件名
语法二 : awk [选项] 'BEGIN{动作}{处理动作1 , 处理动作2...}END{动作}' 文件名
说明 : BEGIN 是指在读awk指定的文件之前要执行的操作 , END 是指在awk读完指定的文件之后执行的操作 .
实例 : 显示 /etc/passwd 文件中以 : (冒号)分隔的第一列内容 :
说明 : 上图命令中 -F : 指定以冒号分隔 , print $1 表示打印出第一列 . 如果不指示符号 , 默认符号为空格 , 可以使用命令 awk '{print $1}' /etc/passwd 对比一下上面的命令显示出来的结果 .
awk的BEGIN , END 语句用法 :
在命令行中执行 : awk 'BEGIN{print "welcome to awk"}' 结果如下 :
执行命令 : awk -F: 'BEGIN{print "welcome to awk"}{print $1}END{print "bye bye"}' /etc/passwd ,从下图可以看出 , 打印出来的 /etc/passwd文件的第一列的开头和节为的内容分别为命令 BEGIN 和 END 语句显示的内容 :
二 . awk 的内置变量
关于awk的内置变量常见的有$0 , FS , OFS :
$0 # 保存当前的整行记录的内容
例 : awk -F: '{print $0}' /etc/passwd , 这条命令显示的是 /etc/passwd 文件的所有内容
FS # 输入字段分隔符 , 默认是空白
例 : awk 'BEGIN{FS=":"}{print $1,$2}' /etc/passwd
OFS #输出字段分隔符 , 默认为空白
例: awk 'BEGIN{FS=":";OFS="@"}{print $1,$2}' /etc/passwd
除了这三种常见的内置变量之外 , 内置变量还有 :
NR #记录号 , 每处理完一条记录 , NR值就加1 , 记录的是文件的总值
可以使用命令 : awk -F: '{print NR,$0}' /etc/passwd 查看效果
FNR #处理多个文件时分别统计自己的NR值
可以使用命令 : awk -F: '{print NR,$0}' /etc/passwd /etc/gshasow 查看效果
NF #表示当前行的字段数(number field)
可以使用命令 : awk -F: '{print NF,$0}' /etc/passwd 查看效果
RS #输入记录分隔符(记录是是行与行之间的分隔) , 默认是一个换行符
可以使用命令 : awk -F: 'BEGIN{RS=":"}{print}' /etc/passwd 查看效果
ORS #输出记录分隔符
可以使用命令 : awk 'BEGIN{ORS=":"}{print}' /etc/passwd 查看效果
以上内置函数不一一举例 , 自行查看效果 ..
三 . awk的逻辑控制语句
前面说到 , awk本身就为一门编程语言 , 所以它本身也自带逻辑控制语句 , 如 if 条件语句 ,for 循环语句等 .
1 . 条件判断 if :
格式 : {if(表达式) {语句 , 语句 ....}}
例 : awk -F: '{if($4>999){print $0}}' /etc/passwd # 显示/etc/passwd 文件中gid大于999的信息
问 : 统计/etc/passwd文件中登录shell为/bin/bash有多少个?
答 : awk -F: '{if($NF=="/bin/bash"){i++}else{j++}}END{print "不是/bin/bash的有 :"j "\n是/bin/bash的有:"i}' /etc/passwd (建议掌握)
注: awk调用内置变量值的时候需要用$变量名 , 而调用自定义变量值的时候不需要$符号 .
2 . 循环语句:
举例说明用法 :
while : 打印1-5数字 awk 'BEGIN{i=1;while(i<=5){print i ;i++}}'
for : 将文件/etc/passwd每一行打印10次 awk -F: '{for(i=1i<=10;i++){print $0}}' /etc/passwd
四 . 数组
例 :统计passwd文件中各种shell类型
awk -F: '{shell[$NF]++} END{for(i in shell){print i,shell[i]}}' /etc/passwd
shell[$NF]++定义了一个名称为shell的数组,$NF(即number field行中的字段数)在passwd中是shell名称,for(i in shell) print i,shell[i],用for循环取出数据来,这时候i取的是下标,shell[i]是里面存储的数据,也是$NF出现的次数
五 . print
1 . print输出 :
要点 : 各个输出字段之间用逗号做分隔 , 而输出默认是以空格做分隔
print 后面如果不指定字段 , 那么会打印一整行
print 输出是默认是有换行符的
例 : 打印与文件内容无关的
awk '{print "aaa"}' /etc/passwd 根据/etc/passwd内容的行数来循环执行print命令
\n换行符
awk -F: '{print $1"\n"$2}' /etc/passwd
\t制表符
awk -F: '{print $1"\t"$2}' /etc/passwd
打印一句话:root用户的uid是0
awk -F: '/^root/{print $1"的uid是"$3}' /etc/passwd
2 . printf格式输出 :
作用 : 可以格式化(format)输出 , 默认不换行
要点 : printf需要指定格式(format)
格式(format)是用来指定后面每个item(条、项目)的输出格式的
printf默认不会自动打印换行符,需要自己动手添加"\n"
printf默认没有输出字段分隔符
使用格式 : printf format itme1
format的指示符都是以%开头的 , 后面跟一个字符 :
%s : 表示字符串
%d : 十进制整数
%f : 表示浮点数(float) , 也就是小数 (%4.2f 其中4表示总显示宽度 , 2表示小数的尾数)
%x : (16进制) %o : (8进制)
修饰符 : %Ns N表示显示宽度(是一个数字)
- : 表示左对齐 , 默认是右对齐
用法 : 例 格式化输出/etc/passwd文件中的用户名 , uid , gid 三列
awk -F: '{printf "%-15s %-5d %-5d\n",$1,$3,$4}' /etc/passwd
echo -e 'hello\nwelcome\nlinux\n1234567890' | awk '{printf "%10s\n",$1}'
echo -e 'hello\nwelcome\nlinux\n1234567890' | awk '{printf "%8s\n",$1}'
六 . awk的比较表达式
比较表达式采用的的是关系运算符 , 用于比较数字与字符串 .
数字与字符串使用的运算符有 :
< 大于 <= 小于等于 = 赋值 == 相等 != 不相等 > 大于 >= 大于等于
例 : 打印 /etc/passwd 文件中的uid=0的账号信息 (图中命令没有写print , 是因为awk会默认执行print命令)
以冒号分隔打印/etc/passwd文件第七列为 /bin/bash的行
七 . awk的匹配模式
/key/ #匹配key关键字
x ~ /key/ #匹配正则 , 其中key可以是正则表达式 , x通常是$1~$n
(awk -F: '$1~/ro/{print $0}' /etc/passwd #打印/etc/passwd第一列包含ro字符的内容行)
x !~/key/ #不匹配正则
(awk -F: '$7 !~/nologin$/' /etc/passwd #打印/etc/passwd中第7列(即登录shell)除了nologin结尾的用户信息)
常见模式 :
1. 空模式 (例 : awk -F: '{print $1}' /etc/passwd #打印文件/etc/passwd第一列 , 不匹配)
2. 固定模式地址 (例 : awk -F: '$1~/^ro/{print $1}' /etc/passwd #打印第一列以ro开头的第一列)
3. 范围模式地址 (例 : awk -F: '/^ro/,/^lp/{print $1}' /etc/passwd #打印以ro开头到lp开头的第1列内容)
注 : awk中不支持行号定址 (反例 : awk -F: '2,5{print $1}' /etc/passwd) ;但用awk的内置变量NR就可以实现类似行号定址的功能 ,如 : (awk 'NR==2,NR==5' /etc/passwd # 输出/etc/passwd文件的第2行至第5行)
八 . 赋值运算
a++ #等同于 a=a+1
a+=5 #等于a=a+5
a+=$n #等同于a=a+$n
例 : 对 /etc/passwd 文件中的 uid 做累加计算
以上就是awk比较全面的介绍及如门操作 !!!