AWK是一门处理文本文件的语言。它把文件看作一串记录(record),缺省情况下一行即为一个记录。每一行又被拆成若干域(field)。我们可以把一行中的第一个词看作第一域,第二个词看作第二域,以此类推
AWK 在1977年被Alfred Aho, Peter Weinberger, and Brian Kernighan开发出来, 和大部分语言一样,AWK是应实际需要而生的。上世纪80年代初,Alfred Aho还是贝尔实验室的研究员。那时需要追踪经费预算。同时因为Alfred Aho在临近的一所大学兼职,追踪学生的成绩也成了一件棘手的事情。
Alfred Aho想要一种小巧的语言,能只写一两行代码就完成这些工作。碰巧Brian Kernighan也有这种需求,于是他们俩一起开发了一个专门针对简易数据处理的模式匹配语言。
GREP对他们的影响很大,它是UNIX下一个很流行的字串匹配工具。GREP也是他们研究中心开发的。GREP可以根据某个正则表达式查找文本文件中特定的行,然后输出它们。
他们想进一步扩展它,使得数字也能向字串那样处理。我们还想在打印之外提供一些计算功能。
开发AWK仅仅是用来满足他们,或是那些对计算机不是很懂的人,处理常规数据的需要。它采取“匹配模式——执行动作”的方式工作
语法形式
awk pattern { action }
awk [ -F fs ] [ -v var=value ] [ 'prog' | -f progfile ] [ file ... ]
上面的语法的意思是根据模式匹配或者调用参数,然后进行你想进行的操作,还是过会来几个例子比较直观点。
参数
-F fs fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:
-v var=value 赋值一个用户定义变量,将外部变量传递给awk
-f scripfile 从脚本文件中读取awk命令
AWK内置变量
CONVFMT 数字转换格式(默认值为%.6g)。
FNR 同NR,但相对于当前文件。
NF 表示字段数,在执行过程中对应于当前的字段数。
NR 表示记录数,在执行过程中对应于当前的行号。
OFMT 数字的输出格式(默认值是%.6g)。
OFS 输出字段分隔符(默认值是一个空格)。
ORS 输出记录分隔符(默认值是一个换行符)。
RS 记录分隔符(默认是一个换行符)。
实例演示
☁ ~ awk "BEGIN { print \"Hello AWK\"}"
Hello AWK
☁ ~ awk 'BEGIN { print "Hello AWK"}'
Hello AWK
☁ ~ awk "BEGIN { print "Hello AWK"}"
awk: syntax error at source line 1
context is
>>> <<<
awk: illegal statement at source line 1
missing }
上面这样的情况是不行的,因为多个引号会让编译器分不清楚主次关系,所以必须加\。
PS: 网上说明shell会对""的参数进行解析,''会比较原汁原味。
个人理解就是""里面如果是变量的话,这个变量会被当成字符串输出。通过下面这个例子实现的。($代表取第几个域,1代表第一列,0代表所有)
☁ ~ echo test|awk '{print $1}'
test
☁ ~ echo test|awk '{print "$1"}'
$1
☁ ~
这次试着使用网上的一些例子,用vi编辑器保存一个文件,并且对这个文件进行搜索等操作。因为支持正则表达式,所以调用上面的格式就能完成这个搜索过程。
☁ Documents cat mail-list
Amelia 555-5553 amelia.zodiacusque@gmail.com F
Anthony 555-3412 anthony.asserturo@hotmail.com A
Becky 555-7685 becky.algebrarum@gmail.com A
Bill 555-1675 bill.drowning@hotmail.com A
Broderick 555-0542 broderick.aliquotiens@yahoo.com R
Camilla 555-2912 camilla.infusarum@skynet.be R
Fabius 555-1234 fabius.undevicesimus@ucb.edu F
Julie 555-6699 julie.perscrutabor@skeeve.com F
Martin 555-6480 martin.codicibus@hotmail.com A
Samuel 555-3430 samuel.lanceolis@shu.edu A
Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R
☁ Documents awk -F "" '{print $1}' mail-list
awk: field separator FS is empty
Amelia
Anthony
Becky
Bill
Broderick
Camilla
Fabius
Julie
Martin
Samuel
Jean-Paul
☁ Documents awk -F "" '/li/ {print $0}' mail-list
awk: field separator FS is empty
Amelia 555-5553 amelia.zodiacusque@gmail.com F
Broderick 555-0542 broderick.aliquotiens@yahoo.com R
Julie 555-6699 julie.perscrutabor@skeeve.com F
Samuel 555-3430 samuel.lanceolis@shu.edu A
上面的一些应该是最基本的使用方法了. 接下来是对awk的内置函数等参数的使用.
语法格式差不多是这个样子:
awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file
第一步:执行BEGIN{ commands }语句块中的语句;
第二步:逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{ commands }语句块。
来计算有多少行可以通过如下命令:
☁ Documents awk 'BEGIN{} { count++ } END{ print count }' mail-list
11
☁ Documents wc -l mail-list
11 mail-list
☁ Documents awk '{ count++ } { print count }' mail-list
1
2
3
4
5
6
7
8
9
10
11
☁ Documents awk 'NR%2==1{next}{print NR,$0}' mail-list
2 Anthony 555-3412 anthony.asserturo@hotmail.com A
4 Bill 555-1675 bill.drowning@hotmail.com A
6 Camilla 555-2912 camilla.infusarum@skynet.be R
8 Julie 555-6699 julie.perscrutabor@skeeve.com F
10 Samuel 555-3430 samuel.lanceolis@shu.edu A
☁ Documents awk '{count++;}{if(count==1) print NR,$1}' mail-list
1 Amelia
☁ Documents awk 'BEGIN{count=0}{while(count<5){ count++;print NR,$1;next }}' mail-list
1 Amelia
2 Anthony
3 Becky
4 Bill
5 Broderick
这条语句如果去掉BEGIN的话就代表每执行一次 count都会被初始化成0。
根据理解, BEGIN是放置一些初始参数的地方, 而且只执行一次, END也只执行一次。
NR 表示记录数. 也是可以通过count来算出第几行, 来选取出你想要的行数或者匹配某一种正则的情况的数据。
代码写的不太规范, 如果想要写一份漂亮规范的awk代码的话最好去网上或者github上面找一些大牛们的脚本。
以上应该是比较简单的AWK的应用了, 贴上一些参考的网站的链接,感觉挺有用的。
Linux The GNU Awk User’s Guide
Linux AWK WIKI
Linux AWK
Linux AWK Leetcode 可以用来练手。