1 开始使用awk
awk的GNU实现称为gawk。简单的认为,学习gawk就是学习awk。
# ll /usr/bin/awk
lrwxrwxrwx. 1 root root 4 10月 25 21:08 /usr/bin/awk -> gawk
当运行awk时,可以指定一个awk程序来告诉awk该怎么做。该程序由一系列规则组成。每个规则指定一个要搜索的模式,并在找到该模式时执行一个动作。从句法上讲,规则由一个模式和一个动作组成。动作用大括号括起来,以将其与模式分开。换行符通常是分开的规则。因此,awk程序如下所示:
pattern { action }
pattern { action }
…
1.1 awk的运行
有几种方法可以运行awk程序。如果程序很短,则最容易将其包含在运行awk的命令中,如下所示:
awk 'program' input-file1 input-file2 …
当程序很长时,通常将其放入文件中更为方便,并使用如下命令运行:
awk -f program-file input-file1 input-file2 …
1.1.1 无输入文件运行awk
示例:
# awk 'BEGIN { print "Don\47t Panic!" }'
Don't Panic!
“\47”是一种神奇的方法,可以将一个引号放入程序中,而不必使用丑陋的shell引号技巧:
# awk "BEGIN { print \" Don't Panic! \" }"
Don't Panic!
注意,单引号在双引号中不是特殊的。特殊符号有 ` $ \ " 这4个,如果在双引号文本中要将这4个符号按字面意思传递给程序不进行转义,这些字符前面需加反斜杠。
下一个简单的awk程序模拟cat实用程序,它将您在键盘上键入的内容复制到标准输出:
# awk '{print}'
Now is the time for all good men
Now is the time for all good men
to come to the aid of their country.
to come to the aid of their country.
Four score and seven years ago,...
Four score and seven years ago,...
what,me worry?
what,me worry?
(ctrl+d)
1.1.2 shell引用的问题(单引号与双引号问题)
# awk 'BEGIN { print "Here is a single quote <'"'"'>" }'
Here is a single quote <'>
混合单引号和双引号是困难的,需要用到这种shell引用技巧。这个程序由三个连在一起的带引号的字符串组成。第一个和第三个是单引号,第二个是双引号。另一种写法如下:
# awk 'BEGIN { print "Here is a single quote <'\''>" }'
Here is a single quote <'>
另一个选项是使用双引号,转义嵌入的awk级别双引号:
# awk "BEGIN { print \"Here is a single quote <'>\" }"
Here is a single quote <'>
第三种方法是对单引号和双引号字符使用八进制转义序列等效值:
# awk 'BEGIN { print "Here is a single quote <\47>" }'
Here is a single quote <'>
# awk 'BEGIN { print "Here is a double quote <\42>" }'
Here is a double quote <">
这方法很好,但是需要清楚转义代表什么。
第四个方法是使用命令行变量赋值:
# awk -v sq="'" 'BEGIN { print "Here is a single quote <" sq ">" }'
Here is a single quote <'>
这里,两个字符串常量和sq的值连接成一个字符串,由print打印。
如果真的需要在awk程序中同时使用单引号和双引号,那么最好将它移到一个单独的文件中。
1.2 用于示例的文件
该文许多示例都是从两个样本文件中获取数据。
第一个文件名为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
每条记录都包含一个人的姓名、电话号码、电子邮件地址以及与作者的关系代码。列使用空格对齐。最后一栏中的“A”表示此人是熟人。最后一栏中的“F”表示此人是朋友。“R”表示此人是亲属。
第二个文件名为inventory-shipped,表示一年中发货的信息。每条记录分别包含月份、装运的绿色板条箱数量、装运的红色盒子数量、装运的橙色袋子数量和装运的蓝色包裹数量。共有16个条目,涵盖去年12个月和今年前四个月。一个空行分隔了两年的数据:
Jan 13 25 15 115
Feb 15 32 24 226
Mar 15 24 34 228
Apr 31 52 63 420
May 16 34 29 208
Jun 31 42 75 492
Jul 24 34 67 436
Aug 15 34 47 316
Sep 13 55 37 277
Oct 29 54 68 525
Nov 20 87 82 577
Dec 17 35 61 401
Jan 21 36 64 620
Feb 26 58 80 652
Mar 24 75 70 495
Apr 21 70 74 514
1.3 一些简单示例
在mail-list中搜索字符串“li”:
# awk '/li/ { print $0 }' mail-list
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规则中,可以省略模式(pattern)或操作(action),但不能同时省略两者。如果省略该模式,则对每个输入行执行该操作。如果省略该操作,则默认操作是打印与模式匹配的所有行。
因此,可以省略前面示例中的操作(print语句和大括号),结果将是相同的:
# awk '/li/' mail-list
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
一些示例:
- 打印超过80个字符的每一行
awk 'length($0) > 80' data
- 打印最长输入行的长度
awk '{ if (length($0) > max) max = length($0) } END { print max }' data
- 打印数据中最长行的长度
expand data | awk '{ if (x < length($0)) x = length($0) } END { print "maximum line length is " x }'
- 打印至少有一个字段的每一行
awk 'NF > 0' data
这是从文件中删除空白行的一种简单方法(或者更确切地说,创建与旧文件相似的新文件,但是已经删除了空白行)。
- 打印0到100之间的七个随机数
awk 'BEGIN { for (i = 1; i <= 7; i++) print int(101 * rand()) }'
- 打印files使用的字节总数
ls -l files | awk '{ x += $5 } END { print "total bytes: " x }'
- 打印所有用户登录名的排序列表
awk -F: '{ print $1 }' /etc/passwd | sort
- 计算文件中的行数
awk 'END { print NR }' data
- 打印数据文件中的偶数行
awk 'NR % 2 == 0' data
如果改用“NR%2==1”表达式,程序将打印奇数行。
参考文档
https://www.gnu.org/software/gawk/manual/gawk.html