Linux的awk命令

版本注意:
该文件的最新版本已经更新到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命令处理流程

  1. 先处理BEGIN字段中的所有内容
  2. 接着将输入的内容按照RS分成一条一条的记录(一行就是一条记录)
  3. 接着将每一行的内容按照FS非常一个一个的字段
  4. 对每一条记录(即每一行)按照PATTERN部分中的内容进行匹配
  5. 完成匹配以后的行,按照{action}部分进行操作。默认的操作是print。
  6. 对每一条记录执行完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命令的注意事项

  1. awk命令中表示每个部分的范围:只能使用单引号,不能使用双引号。
  2. 在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默认会把“数字”下标转换成“字符串”,所以它本质上还是一个使用字符串作为下标的“关联数组”。

  1. 能够用数值作数组索引(下标)
Tarray[1]=“cheng mo”
Tarray[2]=“800927”
  1. 能够用字符串作数组索引(下标)
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  

你可能感兴趣的:(Linux的awk命令)