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匹配到的所有内容。