说明:强大的文本分析语言和工具,一行一行处理,不会内存溢出等问题
强大功能:提取特定的行、指定格式输出、指定格式分割
两种用法:
命令
awk [选项] 'script' var=value files
脚本
awk [选项] -f scriptfile var=value files
选项(常用的选项):
简写 |
全称 |
说明 |
-F fs |
--field-separator fs |
指定分隔符fs,fs可以是字符串或表达式 |
-f scriptfile |
--file scriptfile |
运行awk脚本,里面是awk命令,脚本名随便取 |
-v var=value |
--asign var=value |
给变量var赋值value |
内部变量(表摘自菜鸟教程)
变量 |
描述 |
\$n |
当前记录的第n个字段,字段间由FS分隔 |
\$0 |
完整的输入记录 |
FILENAME |
当前文件名 |
FNR |
各文件分别计数的行号 |
FS |
字段分隔符(默认是任何空格) |
IGNORECASE |
如果为真,则进行忽略大小写的匹配 |
NF |
一条记录的字段的数目 |
NR |
已经读出的记录数,就是行号,从1开始 |
OFS |
输出记录分隔符(输出换行符),输出时用指定的符号代替换行符 |
ORS |
输出记录分隔符(默认值是一个换行符) |
RS |
记录分隔符(默认是一个换行符) |
SUBSEP |
数组下标分隔符(默认值是/034) |
salary.txt 薪水内容,名字,日期,薪水:
sam,2012-01-11,1000
Tom,2012-01-11,2000
John,2012-01-13,3000
sam,2012-01-11,2000
Tom,2013-01-20,3000
John,2013-01-28,4000
实例一:
awk -F, -v OFS="\t" '{print $1,$3}' salary.txt
sam 1000
Tom 2000
John 3000
sam 2000
Tom 3000
John 4000
分析:-F 用,分割数据成,$1,$3 输出第一、第三个字符,-v OFS="\t" 用制表符隔开输出的字段,OFS默认空格
特征:输入、输出格式都可以控制,还可以用printf 控制输出
实例二
awk -F, -v OFS="\t" '$3~/[3-4]000/{print $1,$3,NR}' salary.txt
John
3000
3
分析:$3~/[3-4]000/ 显示第三列满足该正则(3000-4000)的数据,NR是已经读出的记录数,没有显示也数,从1开始
特征:挑选某些数据,合理利用内置变量有时很方便
运算符(表摘自菜鸟教程)
运算符 |
描述 |
= += -= *= /= %= ^= **= |
赋值 |
?: |
C条件表达式 |
|| |
逻辑或 |
&& |
逻辑与 |
~ ~! |
匹配正则表达式和不匹配正则表达式 |
< <= > >= != == |
关系运算符 |
空格 |
连接 |
+ - |
加,减 |
* / % |
乘,除与求余 |
+ - ! |
一元加,减和逻辑非 |
^ *** |
求幂 |
++ -- |
增加或减少,作为前缀或后缀 |
$ |
字段引用 |
in |
数组成员 |
实例三
awk -F, -v OFS="\t" '$3>=2000 && $3<=3000{print $1,$3,NR}' salary.txt
分析:改实例二,不用正则,用运算符,$3>=2000 && $3<=3000,输出同样结果
实例四
awk -F, -v OFS="\t" 'BEGIN{print "name","salary"}{sum+=$3;print $1,$3}END{printf "tatol salary:%d",sum}' salary.txt
name salary
sam 1000
Tom 2000
John 3000
sam 2000
Tom 3000
John 4000
tatol salary:15000
分析:用BEGIN、END做前期和后期工作,sum把第三列工资加起来,在end中用printf输出
特征:前后期工作可以做一些工作,end不想用\t分割输出,就利用printf控制输出格式
内置函数
函数 |
说明 |
rand( ) |
返回任意数 n,其中 0 <= n < 1。 |
srand( [Expr] ) |
将 rand 函数的种子值设置为 Expr,如果省略 Expr 参数则使用某天的时间。返回先前的种子值。 |
sub( Ere, Repl, [ In ] ) |
在In(默认是整个记录($0 记录变量))中,用Repl代替Ere匹配到的字符串,代替一次。返回值是替换的次数。 |
gsub( Ere, Repl, [ In ] ) |
替换所有匹配到字符串,其他和 sub 函数一样。 |
index( String1, String2 ) |
返回string2在string1的位置,从1开始。不在就返回0 |
length [(String)] |
返回string的长度(字节),string默认是$0 |
substr( String, start, [ length ] ) |
取string的子字符串,从start开始,取length个字符(缺省就到末尾) |
match( String, Ere ) |
符合Ere的子字符串在string中位置,没有就返回0。返回值是RSTART特殊变量 |
split( String, A, [Ere] ) |
用Ere或FS特殊变量对string分割,用数组A存储。 |
tolower( String ) |
把string的每个字符都变为小写 |
toupper(string) |
把string的每个字符都变为大写 |
实例五:
awkScript内容如下:
BEGIN{
FS=","
OFS="\t"
print "name","oldname","salary"
}
{
if($3>=2000 && $3<=3000){
sum+=$3
name=tolower($1)
print name,$1,$3
}
}
END{
match("hello world","wo")
printf "total salary:%d\n",sum
printf "the index of wo in hello world:%d\n",RSTART
}
awk -f awkScript salary.txt
name
oldname
salary
分析:运行脚本,选工资2000-3000的,sum记录满足条件全部工资,tolower把名字都小写,match找wo位置,记录在RSART
特征:利用内部函数,快速完成某功能,或者自己做功能,比如统计总工资