大家好,欢迎来到IT知识分享网。
一、awk简介
awk是一个文本分析工具,也可以认为是一种处理文本的语言,之所以叫 AWK 是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。
awk处理的数据来源可以是标准输入、一个或多个文件。支持内置变量、内置函数、运算符、数组、逻辑判断、循环、自定义函数等功能。
二、运行原理
1、命令行执行语法:
awk [选项参数] ‘script’ var=value file(s) (命令行直接写awk程序,即 script)
或者 :awk [选项参数] -f scriptfile var=value file(s) (awk程序写在脚本文件中,即 scriptfile)
其中,file(s)表示输入文本文件可以是多个文件,在程序中可以通过内置变量FILENAME获取当前文件名
主要的选项参数包括:
-f scriptfile-file :从脚本文件中读取awk程序代码
-F fs :指定输入文本的分隔符,默认空格和制表符
-v var=val:自定义变量赋值
2、脚本程序运行原理:
awk ‘BEGIN{ commands } pattern{ commands } END{ commands }’
首先执行开始块: BEGIN {commands} 内的语句块,注意这只会执行一次,经常用于变量初始化、打印表头信息等,在读入数据前就被执行。这里 BEGIN是固定关键字;
其次执行主体块:主体块没有关键字。pattern{ commands }可以有多个,如pattern1{command1} pattern2{command2} 。。。,awk是以行为单位处理的,每读取一行,就顺序执行每一个pattern{commands}。 可以理解成一个for循环,每一行文本是for循环的变量,一个个pattern{commands} 是顺序执行的循环体。
pattern 部分可以是正则表达式、关系表达式或者模式匹配表达式,用来筛选特定文本行,如果pattern为空,则全部选取。
commands 可以是变量或数组赋值、内置函数或自定义函数执行、输出命令、控制流语句等
最后执行 END{ commands } ,也是只会执行一次,在所有行处理完后执行,通常用于打印一些统计结果。
三个部分根据具体情况,都是可有可无。
例如,文本文件 sample.txt 内容如下:
1001,bob,60,500,男
1002,adam,58,300,女
1003,jim,65,700,女
1004,tomas,53,100,男
执行以下命令:
#只输出姓名、年龄两列 awk -F',' '{print $2,$3}' sample.txt bob 60 adam 58 jim 65 tomas 53 #输出年龄大于等于60的所有数据 awk -F',' '$3>=60{print}' sample.txt 1001,bob,60,500,男 1003,jim,65,700,女 #输出姓名中包含字母a的所有数据,并规范格式输出 awk -F',' '$2~/a/{printf "%-7s %-7s %-7s %-7s %-7s\n",$1,$2,$3,$4,$5}' sample.txt 1002 adam 58 300 女 1004 tomas 53 100 男 #格式化输出特定几列(姓名、年龄、金额),并计算输出总金额 awk -F',' 'BEGIN{sum=0;printf "%-7s %-7s %-7s\n","id","age","money"}{sum+=$4;printf "%-7s %-7s %-7s\n",$2,$3,$4}END{print "total money:",sum}' sample.txt id age money bob 60 500 adam 58 300 jim 65 700 tomas 53 100 total money: 1600
三、运算符
= += -= *= /= %= ^= = 赋值
?: C条件表达式
|| 逻辑或
&& 逻辑与
~ 和 !~ 匹配正则表达式和不匹配正则表达式
< <= > >= != == 关系运算符
空格 连接
+ – 加,减
* / % 乘,除与求余
+ – ! 一元加,减和逻辑非
^ * 求幂
++ — 增加或减少,作为前缀或后缀
$ 字段引用
in 数组成员
四、数组
awk支持关联数组
赋值:array_name[index]=value
取值:array_name[index]
删值:delete array_name[index]
模拟多维数组(awk本身不支持多维数组,使用字符串key模拟):array_name[“0,0”]=value00 array_name[“0,1”]=value01
示例:
#数组赋值、取值 awk 'BEGIN {teams["arsenal"]=4;teams["m_city"]=1;print teams["arsenal"]}' 4 #数组删除元素 awk 'BEGIN {teams["arsenal"]=4;teams["m_city"]=1;delete teams["arsenal"];print "m_city:"teams["m_city"]"\n""arsenal:"teams["arsenal"]}' m_city:1 arsenal: #模拟多维数组 awk 'BEGIN {arr["0,0"]=100;arr["0,1"]=200;arr["1,0"]=300;arr["1,1"]=400;print arr["0,0"],arr["0,1"] "\n" arr["1,0"],arr["1,1"]}' 100 200 300 400
五、控制流语句
类似C语言的语法
判断:支持 if(){}、if(){} else{}、if(){} else if(){} else{}
循环:支持 for 、while ,关键字 break(退出循环)、continue(结束本次循环)、exit(结束程序) 控制退出时机
#计算输出每种金额的人数 awk -F',' '{arr[$4]++}END{for(i in arr)print i,arr[i]}' sample.txt sample_2.txt 300 2 600 1 100 1 700 2 500 2
六、内置变量
$n : 当前记录的第n个字段,字段间由FS分隔
$0 : 完整的输入记录
ARGC: 命令行参数的数目
ARGIND: 命令行中当前文件的位置(从0开始算)
ARGV: 包含命令行参数的数组
CONVFMT: 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
ERRNO: 最后一个系统错误的描述
FIELDWIDTHS: 字段宽度列表(用空格键分隔)
FILENAME: 当前文件名
FNR: 各文件分别计数的行号
FS: 字段分隔符(默认是任何空格)
IGNORECASE: 如果为真,则进行忽略大小写的匹配
NF: 一条记录的字段的数目
NR: 已经读出的记录数,就是行号,从1开始
OFMT: 数字的输出格式(默认值是%.6g)
OFS: 输出字段分隔符,默认值与输入字段分隔符一致。
ORS: 输出记录分隔符(默认值是一个换行符)
RLENGTH: 由match函数所匹配的字符串的长度
RS: 记录分隔符(默认是一个换行符)
RSTART: 由match函数所匹配的字符串的第一个位置
SUBSEP: 数组下标分隔符(默认值是/034)
#两个文件顺序输出,并在每一行结尾新增一列,标明来源文件名 awk -F',' 'BEGIN{OFS=","}{print $0,FILENAME}' sample.txt sample_2.txt 1001,bob,60,500,男,sample.txt 1002,adam,58,300,女,sample.txt 1003,jim,65,700,女,sample.txt 1004,tomas,53,100,男,sample.txt 1005,john,61,500,男,sample_2.txt 1006,kody,49,300,女,sample_2.txt 1007,amy,71,700,女,sample_2.txt 1008,saka,70,600,男,sample_2.txt
七、内置函数
主要分为以下几种:
算数函数(atan2、cos、sin、exp、log、sqrt、int、rand、srand)
字符串函数(gsub、sub、substr、index、length、substr、match、split、tolower、toupper、sprintf、strtonum)
时间函数(mktime、strftime、systime)
位操作函数(and、compl、lshift、rshift、or、xor)
其它函数(close、delete、exit、flush、getline、next、nextfile、return、system)
#将姓名列大写输出 awk -F',' '{print toupper($2)}' sample.txt BOB ADAM JIM TOMAS
八、自定义函数
awk支持自定义函数,以提高代码复用性
语法格式:function name(arg1, arg2, …) {…}
#自定义取最小值函数 awk 'function find_min(n1,n2){if(n1<n2) return n1;return n2} BEGIN{result=find_min(2,3);print "mininum=",result}' 2
九、其他例子
1、按不同列排序,如果同一列的值相同,保留另一列的值最大的那个记录
比如用户登录记录:
50025
50025
50026
50026
执行结果为:
50025
50026
脚本如下:
#其中 awk '!a[$1]++' 表示保留第一次出现过的记录 cat login_log.txt | sort -k1b,1 -k2r | awk '!a[$1]++'
2、行列转换
原始文件:
name age
tom 21
lily 20
jim 19
执行结果为:
name tom lily jim
age 21 20 19
脚本如下:
{ for(i=1;i<=NF;i++){ if(!(i in arr)){ arr[i]=$i }else{ arr[i] = arr[i]" "$i } } } END { for(i=1;i<=NF;i++){ print arr[i] } }
3、批量重命名文件
find . -name '*.txt' | awk 'BEGIN{ a=0 }{ printf "mv %s name%01d.txt\n", $0, a++ }' | bash
4、打印九九乘法表
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")}'
5、文本格式修改
原文本:
VFUNC 4718 2020
0 2052
25 2300
50 2512
100 2930
VFUNC 4718 2040
0 2056
25 2302
50 2530
100 2950
修改后文本:
0 2052
25 2300
50 2512
100 2930
0 2056
25 2302
50 2530
100 2950
脚本如下:
NR==1 { f4=$4 f5=$5 } NR>1 && NR<6{ print f4 " " f5 " " $0 } NR==6 { f64=$4 f65=$5 } NR>6 && NR<11{ print f64 " " f65 " " $0 }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/109250.html