说明:强大的文本分析语言和工具,一行一行处理,不会内存溢出等问题
强大功能:提取特定的行、指定格式输出、指定格式分割
两种用法:
命令
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
Tom 3000 5
John 4000 6
分析:$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
tom Tom 2000
john John 3000
sam sam 2000
tom Tom 3000
total salary:10000
分析:运行脚本,选工资2000-3000的,sum记录满足条件全部工资,tolower把名字都小写,match找wo位置,记录在RSART
特征:利用内部函数,快速完成某功能,或者自己做功能,比如统计总工资