因为工作需要,自己接触了并熟悉awk。awk 是一个非常优秀的文本处理工具,用它你可以处理很多问题。
标准的格式: awk [ -F re] [parameter...] ['pattern {action}' ] [-f progfile][in_file...]
在介绍awk使用之前先介绍一下内置变量、函数相关知识:
功能:将string表示的字符串以fieldsep为分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从0开始的序列;
下面我来介绍awk:首先,awk 支持 if-else / while / do-while / for 等这些操作。使用模式有两种,一种是直接操作文件,另一种是使用脚本处理。
(1)简单命令:可以做一些简单的操作
标准的格式: awk [ -F re] [parameter...] ['pattern {action}' ] [-f progfile][in_file...]
在介绍awk使用之前先介绍一下内置变量、函数相关知识:
内置变量:
$0 当前记录行,代表一行记录
$1~$n 当前记录的第n个字段,字段间由FS分隔
ARGC 命令行参数个数 (脚本部分使用)
ARGV 命令行参数排列 (脚本部分使用 ,其就是一个数组)
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行 -F选项
NF 浏览记录的域的个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
BEGIN/END BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。任何在BEGIN之后列出的操作(在{}内)将在Unix awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。
内置函数:
split(string, array [, fieldsep [, seps ] ])功能:将string表示的字符串以fieldsep为分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从0开始的序列;
length([string])
功能:返回string字串中字符的个数
substr(string, start [, length])
功能:取string字符串中的子串,从start开始,取length个;start从1开始计数
system(command)
功能:执行系统command并将结果返回至awk命令
systime()
功能:取系统当前时间
tolower(s)
功能:将s中的所有字母转为小写
toupper(s)
功能:将s中的所有字母转为大写
print和printf
awk中提供了print和printf两个打印输出的函数:print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔;printf函数,的用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,具体格式如下:%c: 显示字符的ASCII码
%d,%i : 显示十进制整数
%e,%E: 科学计数法数值显示
%f : 显示为浮点数
%g,%G: 以科学数法或浮点形式显示数值
%s: 显示字符串
%u: 无符号整数
%%: 显示%号自身,相当于转义
下面我来介绍awk:首先,awk 支持 if-else / while / do-while / for 等这些操作。使用模式有两种,一种是直接操作文件,另一种是使用脚本处理。
(1)简单命令:可以做一些简单的操作
awk -F '分隔符' '{处理过程}' filename(2)复杂命令:可以做一下逻辑比较复杂的操作
例:awk -F ',' '{print $2}' awk.txt
分隔符为 ','
输出$2(输出文件第二列数据);处理过程类似C语言处理
awk.txt 文件名
awk -F '分隔符' 'BEGIN{初始化} {处理过程} END{结束}' filename(3)高阶命令:可以把多个文件放在一起处理
例:awk -F ',' 'BEGIN{print "start ...";sum=0;num=0} {sum+=$2;num++} END{print "end...";print "Average = ",sum/num}' awk.txt
BEGIN 在读取文件文件第一行之前执行,就好像C++的构造函数
end 在读取文件文件最后一行之后执行,就好像C++的析构函数
这个适合用于处理平均值之类的数据 ,num 也可以使用 NR(已读的记录数)替换
awk -F '分隔符' 'BEGIN{初始化} {处理过程} END{结束}' filename1 filename2 。。。(4)脚本处理文件
例:awk -F ',' 'BEGIN{print "start ...";} NR==FNR{a[$3]=$2;} NR!=FNR && a[$4] {printf"%s,%s,%s" ,$1,$4,a[$4]} END{print "end...";print "Average = "}' awk1.txt awk1.txt
NR :已读的记录数
FNR :浏览文件的记录数 ,读取第二个文件的时候就重置了
NR==FNR 表示读取第一个文件
条件正确执行:a[$3]=$2 ==> 以第一个文件的$3字段为下标建立一个数组,这个元素的值为$2
NR!=FNR(不成立时 表示读取第二个文件)
a[$4] :表示第二个文件的$4 字段作为下标读取a[]数组中的值
&&与运算 ,以上两个条件成立则执行后面的处理
awk -F '分隔符' -f 脚本文件 传入的文件(参数的作用)
awk -F ',' -f script.awk filename1 filename2 filename3 。。。
script.awk 为脚本文件,在脚本文件中可以进行多复杂的操作:
如下:
######################################################
function trimcite(v) {vlen=length(v); return substr(v, 2, vlen-2)} #自定义函数
BEGIN {printf("start...\n")}
FILENAME==ARGV[1] && FNR > 1 {name=sprintf("%s%s", $2, $3); map[name]=$1}
FILENAME==ARGV[2] && FNR > 2 {name=sprintf("%s%s", trimcite($2), trimcite($4)); value=map[name]; map_id_ip[$2]=value}
FILENAME==ARGV[3] && FNR > 2 {id=trimcite($3); value=map_id_ip[id];if(map_id_ip[id]) {printf("%s,%s,%s\n", $1, $2,value)}}
END{print {printf("end...\n")}######################################################
(5)awk 根据字段进行去重操作
awk -F '分隔符' '{处理过程}' filename
例:awk -F ',' '!a[$2]++{print}' awk.txt
a[$2]初值为0 ,!a[$2]对应的值为1,则输出整行值;第一次输出以后a[$2] 对应的值为1,2.。。。,!a[$2]对应的值为0,则无输出。