Linux三剑客——awk

发布时间 2023-12-23 22:41:01作者: 换甲

awk命令可以用来的处理数据流,它的作用非常强大,甚至和编程语言一样,甚至实现了条件语句,关联数组等功能。

脚本结构与执行流程

一个典型的awk脚本结构是这样的。

 awk 'BEGIN{   print "start" } pattern { commands } END{ print "end" }' file

这个脚本由三部分组成:

pattern:匹配模式。awk会逐行处理文本,对于能够匹配上pattern的行,会执行公共语句块,也就是实例中的{commands}。

BEGIN:在pattern之前被执行的内容,只执行一次。

END:在pattern之后被执行的内容,也只执行一次。

注意,这三部分都是可选的。

awk的工作流程如下:

(1)首先执行BEGIN { commands } 语句块中的语句。

(2)接着从文件或stdin中读取一行,如果能够匹配pattern,则执行随后的commands语句块。重复这个过程,直到文件全部被读取完毕。

(3)当读至输入流末尾时,执行END { commands } 语句块。

模式是可选的。如果没有提供模式,那么awk就认为所有的行都是匹配的:

 $ echo -e "line1\nline2" | awk 'BEGIN { print "Start" } { print } \
      END { print "End" } '
 Start
 line1
 line2
 End

特殊变量

以下是awk可以使用的一些特殊变量。

  • NR:表示记录编号,当awk将行作为记录时,该变量相当于当前行号。
  • NF:表示字段数量,在处理当前记录时,相当于字段数量。默认的字段分隔符是空格。
  • $0:该变量包含当前记录的文本内容。
  • $1:该变量包含第一个字段的文本内容。
  • $2:该变量包含第二个字段的文本内容。

外部变量

借助选项-v,我们可以将外部值(并非来自stdin)传递给awk:

 

 $ VAR=10000
 $ echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'
 10000

 

还有另一种灵活的方法可以将多个外部变量传递给awk。例如:

 $ var1="Variable1" ; var2="Variable2"
 $ echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2
 Variable1 Variable2

在上面的方法中,变量以键-值对的形式给出,使用空格分隔(v1=$var1 v2=$var2),作为awk的命令行参数紧随在BEGIN、{}和END语句块之后。

过滤

我们可以为需要处理的行指定一些条件:

 

 $ awk 'NR < 5'     # 行号小于5的行
 $ awk 'NR==1,NR==4'     # 行号在1到5之间的行
 $ awk '/linux/'     # 包含模式为linux的行(可以用正则表达式来指定模式)
 $ awk '!/linux/'     # 不包含模式为linux的行

 

读取命令输出

awk可以调用命令并读取输出。把命令放入引号中,然后利用管道将命令输出传入getline:

 "command" | getline output ;

下面的代码从/etc/passwd文件中读入一行,然后显示出用户登录名及其主目录。在BEGIN语句块中将字段分隔符设置为:,在主语句块中调用了grep。

 $ awk 'BEGIN {FS=":"} { "grep root /etc/passwd" | getline; \
      print $1,$6 }'
 root /root

awk的关联数组

除了数字和字符串类型的变量,awk还支持关联数组。关联数组是一种使用字符串作为索引的数组。你可以通过中括号中索引的形式来分辨出关联数组,就像用户定义的简单变量一样,你也可以使用等号为数组元素赋值:

 myarray[index]=value

在awk中使用循环

在awk中可以使用for循环,其格式与C语言中的差不多:

for(i=0;i<10;i++) { print $i ; }

另外awk还支持列表形式的for循环,也可以显示出数组的内容:

for(i in array) { print array[i]; }

awk内建的字符串处理函数

awk有很多内建的字符串处理函数:

  • length(string):返回字符串string的长度。
  • index(string, search_string):返回search_string在字符串string中出现的位置。
  • split(string, array, delimiter):以delimiter作为分隔符,分割字符串string,将生成的字符串存入数组array。
  • substr(string, start-position, end-position):返回字符串string中以start-position和end-position作为起止位置的子串。
  • sub(regex, replacement_str, string):将正则表达式regex匹配到的第一处内容替换成replacment_str。
  • gsub(regex, replacement_str, string):和sub()类似。不过该函数会替换正则表达式regex匹配到的所有内容。