awk入门指南
1.AWK是一种处理文本文件的语言,是一个强大的文本分析工具。之所以叫AWK是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的Family Name的首字符。
2.不同于sed以行为单位,awk是基于列的文本处理工具,它的工作方式是按行读取文本并视为一条记录,每条记录以字段分割成若干字段,然后输出各字段的值。
3.awk认为文件都是结构化的,也就是说都是由单词和各种空白字符组成的,这里的“空白字符” 包括、Tab,以及连续的空格和Tab等。每个非空白的部分叫做“域”,从左到右一次是第一个域,第二个域,等等。
$1、$2分别用于表示域,$0则表示全部域。
awk语法:
awk [选项参数] 'script' var=value file(s)
或者
awk [选项参数] -f scriptfile var=value file(s)
参数 | 作用 |
---|---|
-F fs or --field-separator fs | 指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F: |
-v var=value or --asign var=value | 赋值一个用户定义变量 |
-f scripfile or --file scriptfile | 从脚本文件中读取awk命令 |
-mf nnn and -mr nnn | 对nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用 |
-W compact or --compat, -W traditional or --traditional | 在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略 |
-W copyleft or --copyleft, -W copyright or --copyright | 打印简短的版权信息 |
-W help or --help, -W usage or --usage | 打印全部awk选项和每个选项的简短说明 |
-W lint or --lint | 打印不能向传统unix平台移植的结构的警告 |
-W lint-old or --lint-old | 打印关于不能向传统unix平台移植的结构的警告 |
-W posix | 打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符和=不能代替和=;fflush无效 |
-W re-interval or --re-inerval | 允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]] |
-W source program-text or --source program-text | 使用program-text作为源代码,可与-f命令混用 |
-W version or --version | 打印bug报告信息的版本 |
awk常用的方法:
创建一个awk.txt文件,以此文件为例
[[email protected] ~]# cat awk.txt
john.wang Male 30 021-11111111
lucy.yang Female 25 021-22222222
jack.chen Male 35 021-33333333
lily.gong Female 20 021-44444444 ShangHai
1、打印指定域
既然awk使用$1、$2代表不同的域,则可以打印指定的域。拿awk.txt的第一行来说,第一个域为join.wang,第二个域为Male,第三个域为30、第四个域为021-11111111
打印$1、$4这两个域:
[[email protected] ~]# awk '{print $1,$4}' awk.txt
john.wang 021-11111111
lucy.yang 021-22222222
jack.chen 021-33333333
lily.gong 021-44444444
打印全部内容:
[[email protected] ~]# awk '{print $0}' awk.txt
john.wang Male 30 021-11111111
lucy.yang Female 25 021-22222222
jack.chen Male 35 021-33333333
lily.gong Female 20 021-44444444 ShangHai
2、指定打印分隔符
默认情况下awk是使用空白字符作为分隔符的,但是也可以通过-F参数指定分隔符,来区分不同的域(有点像cut命令)。
指定 “.” 作为分隔符,这样每一行的$1就是 "." 之前的字符,$2就是 "."之后的字符
比如第一行的$1是“join”,$2是“Male 30 021-11111111”
[[email protected] ~]# awk -F. '{print $1}' awk.txt
john
lucy
jack
lily
[[email protected] ~]# awk -F. '{print $2}' awk.txt
wang Male 30 021-11111111
yang Female 25 021-22222222
chen Male 35 021-33333333
gong Female 20 021-44444444 ShangHai
[[email protected] ~]# awk -F. '{print $1,$2}' awk.txt
john wang Male 30 021-11111111
lucy yang Female 25 021-22222222
jack chen Male 35 021-33333333
lily gong Female 20 021-44444444 ShangHai
3、内部变量NF
文件awk.txt所包含的内容不多,所以很容易的知道它的前3行中每行都有4个域,最后一行是5个域。但是如果有时候文件很大,每行列数都不一样,考观察就不现实了,必须通过特定的方式来获得文件的列数。通过awk的内部变量NF可以简单地做到这点。当然,如果指定了不同的分隔符,结果可能不一样
使用默认分隔符:
[[email protected] ~]# awk '{print NF}' awk.txt
4
4
4
5
[[email protected] ~]# awk -F. '{print NF}' awk.txt
2
2
2
2
4、打印固定域
通过内部变量可以简单地得到每行的列数,而如果在NF之前加上$符号,则代表“最后一列”,这样不管每行有多少列,只要使用$NF就能打印出最后一列
打印最后一列:
[[email protected] ~]# awk '{print $NF}' awk.txt
021-11111111
021-22222222
021-33333333
ShangHai
打印倒数第二列:
[[email protected] ~]# awk '{print $(NF-1)}' awk.txt
30
25
35
021-44444444
5、截取字符串
可以使用substr()函数对指定域截取字符串。substr(指定域,第一个开始字符的位置,第二个结束的位置)其中第二个结束的位置可以为空,这样默认输出到该域的最后一个字符
输出awk.txt文件第一个域的第六个字符到最后一个字符的内容:
[[email protected] ~]# cat awk.txt |awk '{print substr($1,6)}'
wang
yang
chen
gong
6、确定字符串的长度
使用内部函数length可以确定字符串的长度。
[[email protected] ~]# cat awk.txt |awk '{print $0}'
john.wang Male 30 021-11111111
lucy.yang Female 25 021-22222222
jack.chen Male 35 021-33333333
lily.gong Female 20 021-44444444 ShangHai
[[email protected] ~]# cat awk.txt |awk '{print length}'
33
33
33
43
7、使用awk求列和
结构化的数据在系统中是随处可见的,比如用ls -l命令得到的输出、各类系统的日志等。在日常工作中,经常有将其中的数据进行相加的需求。
假设awk.txt的第三个域是年龄字段,对所有人的年龄进行计算:
[[email protected] ~]# cat awk.txt |awk 'BEGIN{total=0}{total+=$3}END{print total}'
110
[[email protected] ~]# cat awk.txt |awk 'BEGIN{total=0}{total+=$3}END{print total/NR}'
27.5
上一篇: 米筐社区全方位数据解读
下一篇: java中对日期进行加减操作