Linux中awk命令实例分析

awk是Linux系统中一个优秀的样式扫描与处理工具,要说awk的命令的起源,事实上,它是三个人名的缩写:Aho、Peter Weinberg、Brain Kernighan,因为是他们创造的awk。

awk功能非常强大:除了可以完成grep和sed所能完成的全部工作,还可以进行样式装入、流控制、数学运算符、进程控制语句等等。

与其说awk是一个工具,不如是一种程序设计语言:awk程序设计语言,因为创建者已将它正式定义为“样式扫描和处理语言”。

本文将通过各种实例,来展示awk的功能,如果大家有遇到经典的实例,也可以告诉我哦(会标注原作者的)。

基本语法

awk [-F|-f|-v] 'BEGIN{} //{command1; command2} END{}' file1 file2

参数说明

[-F|-f|-v] -F指定分隔符,-f调用脚本,-v定义变量
' ' 引用代码块
BEGIN 初始化代码块
// 匹配代码块,可以是字符串或正则表达式
{} 命令代码块
; 命令间用分号隔开
END 结束代码块

常用内置变量

$0 当前整行
$[n] 第n个字段
ARGC 命令行参数的数量
ARGV 命令行参数的数组
ENVIRON 支持使用系统环境变量
FILENAME 正在扫描的文件名
FS 在代码块中设置输入分隔符
NF 字段数
NR 记录数
FNR 浏览的文件的记录数
OFS 输出字段分隔符
ORS 输出记录分隔符
RS 控制记录分隔符

常用表达式

length 获取行长度
\t 制表符
\n 换行符
~ 匹配
!~ 不匹配
== 等于
!= 不等于
&& 逻辑与
|| 逻辑或
+ 匹配时表示1个或1个以上
* 匹配通配符
^ 匹配行的开头
$ 匹配行的结尾
/ 转义符
-F'[:;|]' 在“[]”中定义的多个分隔符

实例分析

实例文档awk-example.txt内容如下:

00:2018-06-30;12|23%34,45|56%67,78|89%90,66,123;begin,show some food
01:2018-07-28;12|23%34,45|56%67,78|89%90,66,123;begin,show some food
02:2018-07-29;ab|bc%cd,de|ef%fg,gh|hi%ij,jk,klm;next,buy some vegetables
03:2018-07-30;aa|bb%cc,dd|ee%ff,gg|hh%ii,jj,kkk;other,earn money
04:2018-07-31;11|22%33,44|55%66,77|88%99,66,789;end,go home
05:2018-08-01;1a|2b%3c,4d|5e%6f,7g|8h%9i,0j,0xy;pass,do while night
06:2018-08-02;11|bb%34,de|5e%66,gh|89%ii,jk,789;continue,in the corner
07:2018-08-03;aaa|23i%ccd,4dd|558%6f7,ggy|888%9hi,0jj,xyz;begin,andylouse is a good man
08:2018-08-04;aab|235%cde,4dd|efi%fgg,789|hi8%90i,0jj,abc;again,do well things
09:2018-08-31;aac|123%def,456|opq%678,awk|789%,grep,linux;end,good happiness

1、查找第3-6行中以“,”号分隔的第1、3、5列的内容

awk -F , 'FNR==3,FNR==6 {printf "c1: %s\tc3: %s\tc5: %s\n",$1,$3,$5}' awk-example.txt

2、查找以“%”号分隔的第1列包含“23”的行

awk -F % '$1 ~ /23/{print $0}' awk-example.txt

3、查找以“-”号分隔的第2列等于“07”第3列不包含“28”的行

awk -F - '$2=="07"&&$3!~/28/{printf "%s\n", $0}' awk-example.txt

4、遇到“:”和“;”时均换行并另存为新文件

awk -F'[:;]' '{for(i=1;i<=NF;i++){print $i}}' awk-example.txt > awk-new.txt

awk -F'[:;]' '{for(i=1;i<=NF;i++){print $i}}' awk-example.txt | tee awk-new.txt

5、过滤或替换某列中的字符串

awk 'gsub(/2018-/,"") {print $0}' awk-example.txt

awk -F';' 'gsub(/ /,"-",$3) {print $0}' awk-example.txt

6、计字符串“aa”出现的次数

awk '{s+=gsub(/aa/,"&")}END{print s}' awk-example.txt

练习题

乘法口诀表

seq 9 | sed 'H;g' | awk -v RS='' '{for(i=1;i<=NF;i++)printf("%dx%d=%d%s", i, NR, i*NR, i==NR?"\n":"\t")}'

统计某目录下每个用户的文件占用的磁盘空间

ls -l /data | awk 'NR!=1 {fsum[$3]++;sum[$3]+=$5;du="B";u[0]="G";u[1]="M";u[2]="K";uu[0]=1073741824;uu[1]=1048576;uu[2]=1024;}END{for (i in sum) {for (j=0;j<3;j++) {if (sum[i]>=uu[j]) {sum[i]/=uu[j];du=u[j]; printf "用户: %-8s 文件数: %-5d 总容量: %3.2f %-2s\n",i,fsum[i],sum[i],du;break}}}}'

统计磁盘使用情况

df -m | awk '$1~/^\/dev\//{du+=$3;df+=$4}END{unit="M";if(du>1024 || df>1024){du/=1024;df/=1024;unit="G"} printf "总已用容量:%d%s\n总可用容量:%d%s\n",du,unit,df,unit}'

抓取目录下所有txt文件内容并写入新的文件

find /opt/ip -name "*.txt" | xargs awk '{print}' >> new.ip

awk '{printf "edit bl-%s\nset subnet %s\nnext\n",$1,$1}' new.ip > newest.ip

一个复杂的处理日志的案例

awk '/.*_2[0-2]:/&&$14>500{print $1" "$9" "$14" "$10}' | awk -F'[ /_]' '{s1[$10]+=$7;s2[$10]+=$6;print "时间:"$4"\t速率:"$7/1024/1024/$6*8"\t域名:"$10}END{for(n in s2){print n" "s1[n]/1024/1024/s2[n]*8}}'

列转行输出

softinspath=/opt/zabbix/sbin/zabbix_agent echo $softinspath | awk -F[/] '{for (i=2;i<=NF;i++){print $i}}'

赞 (1) 打赏

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

感谢您的支持与帮助

支付宝扫一扫打赏

微信扫一扫打赏