Not Only Algorithm,不仅仅是算法,关注数学、算法、数据结构、程序员笔试面试以及一切涉及计算机编程之美的内容 。。
你的位置:NoAlGo博客 » 技术 » ,

awk的使用方法

awk是linux对文本和数据进行处理的工具,和sed一样,它也是基于行进行处理,效率很高,在脚本中使用功能非常强大。本文将介绍awk的基本使用方法。

使用方法

awk以其作者的名字命名,它的三个创建者分别是Alfred Aho、Brian Kernighan、Peter Weinberger。awk是行处理器, 它逐行扫描输入文件,寻找匹配的特定模式的行,并在上面执行想要的操作。如果没有指定处理动作,默认把匹配的行显示到标准输出(屏幕);如果没有指定模式,默认所有行都被处理。这种行处理的优点是在处理庞大文件时不会出现内存溢出或是处理缓慢的问题。

awk有几种不同的使用方法。
最简单的是直接在命令行中运行,格式为:

awk 'program' input-file1 input-file2 …

如果程序较长,可以把执行的操作写到脚本中,然后运行:

awk -f program-file input-file1 input-file2 …

另外,也可以编写独立的awk脚本,使得其本身就可以运行。使用linux中的#!机制,可以编写如下代码,保存成为advice,添加可执行的权限,然后就可以直接运行advice了。

#! /bin/awk -f
BEGIN {print "Don't Panic!";}

选项

awk运行时以换行符为标志把文件分成一个个的记录,可以通过内建变量RS改变这个分隔符,另外可以通过内建变量NR得到当前的行号。
然后以空格为分隔符把每个记录分成一个个的域,可以使用内建变量FS改变这个分隔符,分隔符也可以是多个字符,这时任何一个字符都可以把一行记录分隔开。awk中的每个域可以通过如$1、$2等方式引用,而$0表示整一条记录。

比如以下例子中,data文件包含三列,然后使用awk打印了第1列和第3列:

noalgo@AdMin:~$ cat data
1st 2nd 3rd
4th 5th 6th
noalgo@AdMin:~$ awk '{print $1, $3;}' data      
1st 3rd
4th 6th
noalgo@AdMin:~$

使用命令行执行的确切格式为

awk [options] [--] 'commands' input-file(s)

这里的options就是指定运行的参数,比如以上所说的域分隔符即可以使用-F参数进行制定,一些常用的参数如下:

  • -F(–field-separator): 域分隔符。
  • -f(–file): 脚本源文件。
  • -v(–assign): 通过var=val方式设置变量var的值。
  • -C(–copyright): 显示GPL版权信息。
  • -D(–debug=): 允许调试。
  • -h(–help): 显示帮助信息。
  • -V(–version): 显示版本信息。
  • –: 表示选项结束。

内建变量

awk包含很多内建变量,可以在代码中进行使用,下面先介绍以供后续使用。

一些控制awk工作的内建变量如下:

  • RS(input record separator): 记录分隔符。
  • ORS(output record separator): 输出记录分隔符。
  • FS(field separator): 域分隔符。
  • OFS(output field separator): 输出域分隔符。

一些传递信息的内建变量如下:

  • ARGC, ARGV: 命令行产生个数及具体内容。
  • FILENAME: 正在处理的文件名。
  • NF(#fields): 当前记录的域数量。
  • NR(#records): 当前已处理的记录数目,一直累加。
  • FNR(#records in current file): 当前文件的记录数目,每个文件会重置。

以下简单演示下内建变量NR和FILENAME,跟每行添加一个行号,并最终打印记录个数。

noalgo@AdMin:~$ awk '{print NR-1, $0;} END {printf "%s has %d records.\n", FILENAME,  NR-1;}' data 
0 ID    NAME    SCORE
1 001   AAA     10
2 002   BBB     9
3 003   CCC     3
data has 3 records.

命令

awk里面的commands是真正的awk命令,awk中一般有多条语句,而每条语句都由模式和动作组成,其格式为:

pattern {action}

具体的功能为:

  • 模式部分决定动作语句何时触发,如果没有指定,默认对所有行都进行操作。
  • 动作部分决定对数据进行的操作,如果没有指定,默认对所有内容进行输出。

而其中的模式可以包括很多内容:

  • 关系表达式:使用关系运算符进行选择,包括<、<=、>、>=、==、!=等。
  • 正则表达式:根据正则表达式判断是否匹配,可以使用~或!~进行匹配。
  • BEGIN: 在第一行读入之前就进行的操作。
  • END: 在最后一行读取之后才进行的操作。

一些简单例子如下:

noalgo@AdMin:~$ cat data  文件内容
ID      NAME    SCORE
001     AAA     10
002     BBB     9
003     CCC     3
noalgo@AdMin:~$ awk '/[0-9]+/ {print $0;}' data 匹配一个以上数字的行
001     AAA     10
002     BBB     9
003     CCC     3
noalgo@AdMin:~$ awk '$2=="AAA" {print $0;}' data 精确匹配
001     AAA     10
noalgo@AdMin:~$ awk '$2=="AAA" || NR==1 {print $0;}' data 加上首行
ID      NAME    SCORE
001     AAA     10
noalgo@AdMin:~$ awk '$2~"A" {print $0;}' data    匹配
ID      NAME    SCORE
001     AAA     10
noalgo@AdMin:~$ awk '$2!~"A" {print $0;}' data   不匹配
002     BBB     9
003     CCC     3
noalgo@AdMin:~$ awk '$3>5 {print $0;}' data
ID      NAME    SCORE
001     AAA     10
002     BBB     9
noalgo@AdMin:~$ awk '$3>5 && $1<2 {print $0;}' data                                                  
001     AAA     10
noalgo@AdMin:~$ awk 'BEGIN {print "Begin..";} {print $2;} END {print "End..";}' data
Begin..
NAME
AAA
BBB
CCC
End..
noalgo@AdMin:~$

动作必须包含在{}内部,可以包含如打印、判断、循环等复杂操作。awk实际有其自身独自的程序设计语言,可以声明变量或数组,调用函数,使用判断、循环等控制流等。

awk内部包含了若干常用的字符串处理函数:

  • gsub(r,s): 在$0中使用s替代r。
  • index(s,t): 返回s中t出现的第一个位置。
  • length(s): 返回s的长度。
  • match(s,r): 测试s是否包含匹配r的字符串。
  • split(s,a,fs): 在fs上将s分成序列a
  • sprint(fmt,exp): 返回经fmt格式化后的exp。
  • sub(r,s): 从$0中最左边最长的子串中用s代替r。
  • substr(s,p): 返回s中从p开始的后缀。
  • substr(s,p,n):返回s中从p开始长度为n的后缀。

下面提供一些简单的小示例。

选择学号小于2成绩大于5的行进行打印:

noalgo@AdMin:~$ awk '{score=$3; id=$1; if(score>5 && id<2) print $0;}' data 
001     AAA     10

计算平均分:

noalgo@AdMin:~$ awk '{tot+=$3;} END {print "Average score:", tot/(NR-1);}' data 
Average score: 7.33333

找出名字包含A的记录:

noalgo@AdMin:~$ awk 'match($2, "A") && NR>1 {print $2, $3}' data
AAA 10

下面演示数组及循环的使用方法:

noalgo@AdMin:~$ awk 'BEGIN {count=0;} {if (count > 0) name[count]=$2; count++;} END {for (i=1; i<NR; i++) printf "The %d student: %s\n", i, name[i];}' data 
The 1 student: AAA
The 2 student: BBB
The 3 student: CCC
noalgo@AdMin:~$ 

统计/etc/passwd的账户及总数:

noalgo@AdMin:/$ awk -F ':' '{count++; print $1;} END {print "User count is", count;}' /etc/passwd
root
daemon
bin
...以下省略28行
User count is 31

统计文件夹下文件的大小总和:

noalgo@AdMin:~$ ls -l | awk 'BEGIN {size=0;} {size+=$5} END {print "Size is", size;}'
Size is 1653606
上一篇: 下一篇:
  1. 晚上去奶奶家吃饭,过程中各种说不完的话,吃完饭要走的时候爷爷突然说了句没事多来和我说说话。当时心里一阵阵酸痛。

  2. 学好IT好就业选硅谷IT,学技能拿文凭事半功倍,紧跟专业教师一起冲浪IT行业。我们有建设学习型专业师资团队,教师领跑学生紧随其后。

我的博客

NoAlGo头像编程这件小事牵扯到太多的知识,很容易知其然而不知其所以然,但真正了不起的程序员对自己程序的每一个字节都了如指掌,要立足基础理论,努力提升自我的专业修养。

站内搜索

最新评论