核心
1、什么是awk
2、awk的工作原理
3、awk的选项介绍
4、基本使用
5、运算符
6、内建变量
7、案例
1、什么是awk
AWK是一种处理文本文件的语言,是一个强大的文本分析工具。
之所以叫AWK是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的Family Name的首字符。
2、awk的工作原理
awk ‘BEGIN{ commands } pattern{ commands } END{ commands }’
第一步:执行BEGIN{ commands }语句块中的语句;
第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{ commands }语句块。 BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。 END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。
3、awk的选项介绍
awk的语法格式
awk [选项参数] ‘script’ var=value file(s)
或
awk [选项参数] -f scriptfile var=value file(s)
选项参数说明
1、 -F fs or –field-separator fs
指定输入文件拆分隔符,fs是一个字符串或者一个正则表达式 如-F: 表示按照:字符来做分隔
2、-v val=value or –asign var=value
赋值一个用户自定义变量,Linux我们一般是用${val}来使用一个变量但是awk不行,需要用-v来赋值
3、-f scriptfile or –file scriptfile
从脚本文件中读取awk命令
4、-mf nnn and -mr nnn
对nnn值设置内在限制,-mf 选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目,这2个功能是bell
实验室版awk的扩展功能,在标准awk中不适用
5、-W compact or –compat,-W traditional or –traditional
在兼容模式下运行awk,所以gawk的行为和标准的awk一样,所有的awk扩展都被忽略
6、-W copylefe or –copyleft ,-W copyright or –copyright
打印简短的版权信息
7、 -W help or –help ,-W usage or –usage
打印全部awk选项和每个选项的简短说明
8、-W lint or –lint
打印不能向传统unix平台移植的结构的告警
9、-W lint-old or –lint-old
打印关于不能向传统unix平台移植的结构的告警
10、-W posix
打开兼容模式,但是有以下限制,不识别:/x、函数关键字、
func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;
操作符**和**=不能替代^和^=;fflush无效
11、-W re-interval or –re-inerval
允许间隔正则表达式的使用, 如括号表达式 [[:alpha:]]
12、-W source program-text or –source program-text
使用program-text 作为源代码,可与-f 命令混用
13 -W version or –version
打印信息版本
4、基本使用
log.txt文本内容如下:
bigdata hadoop spark storm
java scala c C++
shell python,cpython,Ppython,jpython
用法一:
awk ‘{[pattern] action}’ {filenames} # 行匹配语句 awk ” 只能用单引号
实例
按照空格或者tab键做分隔,输出第一列和第4列的值 。这里awk的默认分隔符就是空格,所以我们没有必要指定
[root@SZB-L0032013 awk]# awk '{print $1,$4}' log.txt
bigdata storm
java C++
shell
输出格式化
[root@SZB-L0032013 awk]# awk '{printf "%-8s %-10s\n",$1,$4}' log.txt
bigdata storm
java C++
shell
用法二:
awk -F #-F相当于内置变量FS, 指定分割字符
#使用","做分隔符
[root@SZB-L0032013 awk]# awk -F, '{print $1,$2}' log.txt
bigdata hadoop spark storm
java scala c C++
shell python cpython
# 或者使用内建变量,这里的BEGIN需要大写
[root@SZB-L0032013 awk]# awk 'BEGIN{FS=","} {print $1,$2} ' log.txt
bigdata hadoop spark storm
java scala c C++
shell python cpython
# 使用多个分隔符.先使用空格分割,然后对分割结果再使用”,”分割
[root@SZB-L0032013 awk]# awk -F '[ ,]' '{print $1,$2,$5}' log.txt
bigdata hadoop
java scala
shell python jpython
用法三:
awk -v #设置变量
[root@SZB-L0032013 awk]# awk -v a=1 '{print a+1,$1}' log.txt
2 bigdata
2 java
2 shell
[root@SZB-L0032013 awk]# awk -va=1 -vb=s '{print $1,$1+a,$1b}' log.txt
bigdata 1 bigdatas
java 1 javas
shell 1 shells
用法四
awk -f {awk脚本} {文件名}
$ awk -f cal.awk log.txt
[root@SZB-L0032013 awk]# cat awk.file
#!/bin/awk -f
-F " " {print $1}
[root@SZB-L0032013 awk]# awk -f awk.file log.txt
bigdata
java
shell
5、运算符
= += -= *= /= %= ^= **= 赋值
?: C条件表达式
|| 逻辑或
&& 逻辑与
~ ~! 匹配正则表达式和不匹配正则表达式
< <= > >= != == 关系运算符
空格 连接
+ - 加,减
* / % 乘,除与求余
+ - ! 一元加,减和逻辑非
^ *** 求幂
++ -- 增加或减少,作为前缀或后缀
$ 字段引用
in 数组成员
案例
[root@SZB-L0032013 awk]# awk '{print $1}' log.txt
bigdata
java
shell
[root@SZB-L0032013 awk]# awk '$1=="shell" || $1=="java" {print $1}' log.txt
java
shell
[root@SZB-L0032013 awk]# awk '{print $1}' log.txt
bigdata
java
shell
[root@SZB-L0032013 awk]# awk '$1>"c" {print $1}' log.txt
java
shell
注意:> < 可以作为字符串比较,也可以用作数值比较,关键看操作数如果是字符串就会转换为字符串比较。两个都为数字才转为数值比较。字符串比较:按照ASCII码顺序比较。
[root@SZB-L0032013 awk]# awk 'BEGIN{a="b";print a=="b"? "true":"false";}'
true
[root@SZB-L0032013 awk]# awk 'BEGIN{a="b";arr[0]="a";arr[1]="c";print(a in arr)}'
0
[root@SZB-L0032013 awk]# awk 'BEGIN{a="b";arr[0]="b";arr["b"]="c";print(a in arr)}'
1
正则表达式,第一列中包含big单词的行,打印出第一列和第二列
~ 表示匹配模式的开始 //表示需要匹配的模式
[root@SZB-L0032013 awk]# awk '$1 ~ /big/ {print $1,$2}' log.txt
bigdata hadoop
[root@SZB-L0032013 awk]# cat log.txt
bigdata hadoop spark storm
java scala c C++
shell python,cpython,Ppython,jpython
#匹配包含有shell的行,相当于 grep
[root@SZB-L0032013 awk]# awk '/shell/' log.txt
shell python,cpython,Ppython,jpython
#模式取反操作
[root@SZB-L0032013 awk]# awk ' !/hadoop/' log.txt
java scala c C++
shell python,cpython,Ppython,jpython
Hadoop drill hive
[root@SZB-L0032013 awk]# awk '$1 !~ /big/ {print $1,$2}' log.txt
java scala
shell python,cpython,Ppython,jpython
Hadoop drill
6、内建变量
\$n 当前记录的第n个字段,字段间由FS分隔
\$0 完整的输入记录
ARGC 命令行参数的数目
ARGIND 命令行中当前文件的位置(从0开始算)
ARGV 包含命令行参数的数组
CONVFMT 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
ERRNO 最后一个系统错误的描述
FIELDWIDTHS 字段宽度列表(用空格键分隔)
FILENAME 当前文件名
FNR 同NR,但相对于当前文件
FS 字段分隔符(默认是任何空格)
IGNORECASE 如果为真,则进行忽略大小写的匹配
NF 当前记录中的字段数
NR 当前记录数
OFMT 数字的输出格式(默认值是%.6g)
OFS 输出字段分隔符(默认值是一个空格)
ORS 输出记录分隔符(默认值是一个换行符)
RLENGTH 由match函数所匹配的字符串的长度
RS 记录分隔符(默认是一个换行符)
RSTART 由match函数所匹配的字符串的第一个位置
SUBSEP 数组下标分隔符(默认值是/034)
[root@SZB-L0032013 awk]# awk 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s\n","FILENAME","FNR","FS","NF","NR","ARGC","ARGIND\n";printf "-------------------------------------------------\n"}{printf "%4s %4s %4s %4s %4s %4s %4s\n",FILENAME,FNR,FS,NF,NR,ARGC,ARGIND}' log.txt
FILENAME FNR FS NF NR ARGC ARGIND
-------------------------------------------------
log.txt 1 4 1 2 1
log.txt 2 4 2 2 1
log.txt 3 2 3 2 1
[root@SZB-L0032013 awk]# awk -F "=" 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s\n","FILENAME","FNR","FS","NF","NR","ARGC","ARGIND\n";printf "-------------------------------------------------\n"}{printf "%4s %4s %4s %4s %4s %4s %4s\n",FILENAME,FNR,FS,NF,NR,ARGC,ARGIND}' log.txt
FILENAME FNR FS NF NR ARGC ARGIND
-------------------------------------------------
log.txt 1 = 1 1 2 1
log.txt 2 = 1 2 2 1
log.txt 3 = 1 3 2 1
[root@SZB-L0032013 awk]# awk '{print NR,FNR,$1,$2,$3}' log.txt
1 1 bigdata hadoop spark
2 2 java scala c
3 3 shell python,cpython,Ppython,jpython
[root@SZB-L0032013 awk]# awk '{print NR,FNR,$1,$2,$3}' OFS="$" log.txt
1$1$bigdata$hadoop$spark
2$2$java$scala$c
3$3$shell$python,cpython,Ppython,jpython
忽略大小写匹配
[root@SZB-L0032013 awk]# awk 'BEGIN{IGNORECASE=1} /hadoop/' log.txt
bigdata hadoop spark storm
Hadoop drill hive
[root@SZB-L0032013 awk]# awk '/hadoop/' log.txt
bigdata hadoop spark storm
7、案例
有一个文件 sorce.txt里面是各个同学的分数信息,现在需要统计每个同学的总成绩和平均成绩
[root@SZB-L0032013 awk]# cat sorce.txt
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2122 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62
[root@SZB-L0032013 awk]# cat awk.file
#!/bin/awk -f
#BEGIN
BEGIN{
FS=" "
math=0
english=0
computer=0
printf "NAME NO. MATH ENGLISH COMPUTER TOTAL\n"
printf "-----------------------------------------------\n"
}
#cal
{
math+=$3
english+=$4
computer+=$5
printf "%-6s %-4s %8d %8d %8d %8d\n",$1,$2, $3,$4,$5, $3+$4+$5
}
#END
END{
printf "-----------------------------------------------\n"
printf "TOTAL: 10%d %8d %8d \n",math,english,computer
printf "AVG: 10.2%d %8.2d %8.2d\n",math/NR,english/NR,computer/NR
}
运行的结果是
[root@SZB-L0032013 awk]# awk -f awk.file sorce.txt
NAME NO. MATH ENGLISH COMPUTER TOTAL
-----------------------------------------------
Marry 2143 78 84 77 239
Jack 2321 66 78 45 189
Tom 2122 48 77 71 196
Mike 2537 87 97 95 279
Bob 2415 40 57 62 159
-----------------------------------------------
TOTAL: 10319 393 350
AVG: 10.263 78 70
其他的案例
统计一个目录下面文件的总大小
[root@SZB-L0032013 ProCAppnt]# ls -l *.txt|awk 'BEGIN{FS=" "} {sum+=$5} END{print sum/1024/1024"MB"}'
1032.93MB
统计行长度大于20的记录
[root@SZB-L0032013 awk]# awk 'length>20' log.txt
bigdata hadoop spark storm
shell python,cpython,Ppython,jpython