awk学习笔记

awk学习笔记一 awk 简介 awk 是一个文本分析工具 也可以认为是一种处理文本的语言 之所以叫 AWK 是因为其取了三位创始人 Alfred Aho Peter Weinberger 和 Brian Kernighan 的 Family Name 的首

大家好,欢迎来到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

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信