版本注意:
该文件的最新版本已经更新到MWeb中了,请以那边为准,这儿仅供参考。
Linux的awk命令
众所周知awk命令是Linux一个非常重要又难以掌握的命令,下面对这个命令进行一个详细的说明。
更新额外的参考文档:
- 阮一峰大神写的一篇文章: awk 入门教程
- runoob网站的:Linux awk 命令
- awk的一本好书:Gawk: Effective AWK Programming
最后推荐的这本好书是纯英文的,需要一些英文阅读能力。
awk命令的语法格式
awk命令的语法格式如下:
awk [options] 'pattern{action}' file
option选项
首先【options】可以省略,常用的参数如下。
-v 用于设置变量值。
-F 用于指定分割字符,相当于内置变量FS。
pattern部分
pattern部分包括两种特殊的格式,分别是BEGIN和END。
现在假设有一个文件test.txt,其内容是:
123 abc 321
456 654 def
fhi 789 987
(1)BEGIN模式,是指在awk命令正式处理每一行之前要进行的操作。
awk 'BEGIN{print "ceshi1","ceshi2","ceshi3"} {print}' test.txt
那么打印出来的效果是:
ceshi1 ceshi2 ceshi3
123 abc 321
456 654 def
fhi 789 987
(2)END模式,是指在awk命令正式处理每一行以后再进行的操作。
awk '{print} END{print "ceshi1","ceshi2","ceshi3"}' test.txt
那么打印出来的效果是:
123 abc 321
456 654 def
fhi 789 987
ceshi1 ceshi2 ceshi3
(3)在BEGIN和END之间,通常都会有一个大括号{},大括号里面一般都会有一些语句。
注意:这个大括号里面的语句是对文件中的每一行都执行一遍操作。
awk 'BEGIN{print "ceshi1","ceshi2","ceshi3"} {print $1} END{print "ceshi4","ceshi5","ceshi6"}' test.txt
那么打印出来的效果是:
ceshi1 ceshi2 ceshi3
123
456
fhi
ceshi4 ceshi5 ceshi6
其中{print $1},代表的是打印第一个字段。因为这个操作会对每一行执行,所以最终的结果就是打印每一行的第一个字段。
awk命令的处理流程
先说几个名词:
- 记录:每一行就是每一条记录,awk命令区分每一行的方式是按照内部变量【RS】来执行的。awk默认的RS值是【\n】,即:每遇到一个【\n】awk就知道又换了一行。
- 字段:由内部变量【FS】将每一行中的内容分为很多小块,每个小块就是一个字段。第一个小块,为字段1,如果引用的话,采用变量【$1】。awk默认的FS值是空格,即:每遇到一个空格,awk就知道又换了一个字段。
awk命令处理流程
- 先处理BEGIN字段中的所有内容
- 接着将输入的内容按照RS分成一条一条的记录(一行就是一条记录)
- 接着将每一行的内容按照FS非常一个一个的字段
- 对每一条记录(即每一行)按照PATTERN部分中的内容进行匹配
- 完成匹配以后的行,按照{action}部分进行操作。默认的操作是print。
- 对每一条记录执行完PATTERN{action}部分以后,执行END语句中的内容。
awk中的变量
awk命令作为一个非常强大的命令,与其强大的内置变量、自定义变量有很大的关系
awk内置的变量
awk内置的变量如下:
变量名称 | 变量的含义 | 重要级 |
---|---|---|
$0 | 当前行(这个变量中存放着整个行的内容) | ** |
$1 | 当前行中的第1个字段,字段间由FS分隔 | ** |
$2 | 当前行中的第2个字段,字段间由FS分隔。后面的类似。 | ** |
FS | 输入字段分隔符,默认为空白字符 | **** |
OFS | 输出字段分隔符,默认为空白字符 | **** |
RS | 输入记录分隔符(输入换行符),指定输入时的换行符 | ** |
ORS | 输出记录分隔符(输出换行符),指定输出时的换行符 | ** |
NF | 当前行的字段数(当前行被分隔符分割成了几段) | ** |
NR | 当前行的行号 | ***** |
FNR | 不同文件分别计数 | |
FILENAME | 当前文件名 | |
ARGV | 数组,保存的是命令行所给定的各参数 | |
ARGC | ARGC数组的个数 |
awk的自定义变量
在awk中直接定义变量的方法如下:
awk 'BEGIN{var=100; print var} {print $2,$3}' test.txt
那么打印出来的效果是:
100
abc 321
654 def
789 987
awk命令的注意事项
- awk命令中表示每个部分的范围:只能使用单引号,不能使用双引号。
- 在awk中数字数组也是通过引用下标的方法,但是在awk中数字数组的下标是从1开始的,而非常规的0。
awk命令的一些实例
awk常规的匹配用法
过滤出log.txt文件中:第一列大于2的行
awk '$1>2' log.txt
## 因为awk默认执行的是print操作,如果没有指定动作,它就把匹配的内容打印出来。
过滤第一列大于2并且第二列等于’Are’的行
awk '$1>2 && $2=="Are" {print $1,$2,$3}' log.txt
## {print $1,$2,$3} 语句打印出每个匹配行的前三个字段。
将第一列与第3列使用->连接并将第3列以16进制输出:
awk -F: '{printf "%s->%x\n", $1,$3}' /etc/passwd
## -F参数与后面的冒号,表示是以冒号为分隔符的。
awk命令的正则运算
awk -F: '/root/ {print $1,$3,$0}' /etc/passwd
## 输出包含有root的行,并打印用户名和UID及原行内容
awk命令的三目运算
awk 'BEGIN{a="b";print a=="b"?"ok":"err"}'
## 三目运算其实就是一个判断运算,如果为真则输出?后的内容,如果为假则输出:后的内容
awk命令的循环语句
if语句
awk 'BEGIN{ test=100;if(test>90){ print "vear good";} else{print "no pass";}}'
## 每条命令后用;结尾
while语句
awk 'BEGIN{test=100;num=0;while(i<=test){num+=i; i++;}print num;}'
## 计算从1累加到100的值
awk命令的数组运算
数组是awk的灵魂,处理文本中最不能少的就是它的数组处理。
awk中数组的特点:
- awk 中的数组不必提前声明,也不必声明大小。
- 数组元素用0或空字符串来初始化,这根据上下文而定。
一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。
在awk中数组叫做关联数组(associative arrays)。
在awk中数组的下标不仅可以是“数字”,还可以是“任意字符串”,其实,awk中的数组本来就是“关联数组”,之所以先用数字作为下标举例子是为了方便之前的习惯,能够有个好的过渡,不过,以数字作为数组的下标在某些场景有一定的优势,但是本质上也是“关联数组”,awk默认会把“数字”下标转换成“字符串”,所以它本质上还是一个使用字符串作为下标的“关联数组”。
- 能够用数值作数组索引(下标)
Tarray[1]=“cheng mo”
Tarray[2]=“800927”
- 能够用字符串作数组索引(下标)
Tarray[“first”]=“cheng ”
Tarray[“last”]=”mo”
Tarray[“birth”]=”800927”
下面是一个显示/etc/passwd的账户的awk语句
awk -F: 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd