linux gawk 程序学习


gawk 程序是 Unix 中的原始 awk 程序的 GNU 版本。
gawk 程序让流编辑器迈上了一个新的台阶,它提供了一种编程语言而不只是编辑器命令。在 gawk 编程语言中,你可以做下面的事情:

  • 定义变量来保存数据;
  • 使用算数和字符串操作符来处理数据;
  • 使用结构化编程概念(比如 if-then 语句和循环)来为数据处理增加处理逻辑;
  • 通过提取数据文件中的数据元素,将其重新排列或格式化,生成格式化报告。

gawk 程序的报告生成能力通常用来从大文本文件中提取数据元素,并将它们格式化成可读的报告。其中最完美的例子是格式化日志文件。在日志文件中找出错误行会很难,gawk 程序可以让你从日志文件中过滤出需要的数据元素,然后你可以将其格式化,使得重要的数据更易于阅读。

1. gawk 数据格式

gawk 程序的基本格式如下:

gawk options program file
gawk 选项
选项描述
-F fs指定行中划分数据字段的字段分隔符
-f file从指定的文件中读取程序
-v var=value定义 gawk 程序中的一个变量及其默认值
-mf N指定要处理的数据文件中的最大字段数
-mr N指定数据文件中的最大数据行数
-W keyword指定 gawk 的兼容模式或警告等级

2. 从命令行读取程序脚本

gawk 程序脚本用一对花括号来定义。你必须将脚本命令放到两个花括号 {} 中。
由于 gawk 命令行假定脚本是单个文本字符串,因此需要将脚本放到单引号中。

$ gawk '{print "hello world!"}'

这个程序脚本定义了一个命令:print 命令,它会将文本打印到 STDOUT。如果尝试运行这个命令,你可能会有些失望,因为什么都不会发生。原因在于没有在命令行上指定文件名,所以 gawk 程序会从 STDIN 接收数据。在运行这个程序时,它会一直等待从 STDIN 输入的文本。

如果你输入一行文本并按下回车键,gawk 会对这行文本运行一遍程序脚本。跟 sed 编辑器一样,gawk 程序会针对数据流中的每行文本执行程序脚本,由于程序脚本被设为显示一行固定的文本字符串,因此不管你在数据流中输入什么文本,都会得到同样的文本输出。

$ gawk '{print "hello world!"}'
This is a test
hello world!
hello
hello world!
This is another test
hello world!

要终止这个 gawk 程序,你必须标明数据流已经结束了。bash shell 提供了一个组合键来生成 EOF(End-of-File)字符。Ctrl+D 组合键会在 bash 中产生一个 EOF 字符。这个组合键能够终止该 gawk 程序并返回到命令行界面提示符下。

3. 使用数据字段变量

gawk 的主要特性之一是其处理文本文件中数据的能力。它会自动给一行中的每个数据元素分配一个变量。默认情况下,gawk 会将如下变量分配给它在文本行中发现的数据字段:

  • $0 代表整个文本行;
  • $1 代表文本行中的第 1 个数据字段;
  • $2 代表文本行中的第 2 个数据字段;
  • $n 代表文本行中的第 n 个数据字段。

在文本行中,每个数据字段都是通过字段分隔符划分的。gawk 在读取一行文本时,会用预定义的字段分隔符划分每个数据字段。gawk 中默认的字段分隔符时任意的空白字符(例如空格或制表符)。

在下面的例子中,gawk 程序读取文本文件,只显示第 1 个数据字段的值。

$ cat data2.txt 
One line of test text.
Two lines of test text.
Three lines of test text.
$
$ gawk '{print $1}' data2.txt 
One
Two
Three
$

该程序用 $1 字段变量来仅显示每行文本的第 1 个数据字段。

如果你要读取采用了其他字段分隔符的文件,可以用 -F 选项指定。

$ gawk -F: '{print $1}' /etc/passwd
root
daemon
bin
sys
sync
games
man
lp
mail
[...]

这个简短的程序显示了系统中密码文件的第 1 个数据字段。由于 /etc/passwd 文件用冒号来分隔数字字段,因而如果要划分开每个数据元素,则必须在 gawk 选项中将冒号指定为字段分隔符。

4. 在程序脚本中使用多个命令

gawk 允许你将多条命令组合成一个正常的程序。要在命令行上的程序脚本中使用多条命令,只要在命令之间放个分号即可。

$ echo "My name is Rich" | gawk '{$4="Christine"; print $0}'
My name is Christine
$

第一条命令会给字段比变量 $4 赋值,第二条命令会打印整个数据字段。

也可以用次提示符一次一行地输入程序脚本命令。

$ gawk '{
> $4="Christine"
> print $0}'
My name is Rich
My name is Christine
$

5. 从文件中读取程序

$ cat script2.gawk 
{print $1 "'s home directory is " $6}
$
$ gawk -F: -f script2.gawk /etc/passwd
root's home directory is /root
daemon's home directory is /usr/sbin
bin's home directory is /bin
sys's home directory is /dev
sync's home directory is /bin
games's home directory is /usr/games
man's home directory is /var/cache/man
lp's home directory is /var/spool/lpd
[...]
$

script2.gawk 程序脚本会再次使用 print 命令打印 /etc/passwd 文件的主目录数据字段(字段变量 $6) 以及 userid 数据字段(字段变量 $1)。

可以在程序文件中指定多条命令。要这么做的话,只要一条命令放一行即可,不需要分号。

$ cat script3.gawk 
{
    text = "'s home directory is "
    print $1 text $6
}
$
$ gawk -F: -f script3.gawk /etc/passwd
root's home directory is /root
daemon's home directory is /usr/sbin
bin's home directory is /bin
sys's home directory is /dev
sync's home directory is /bin
games's home directory is /usr/games
man's home directory is /var/cache/man
lp's home directory is /var/spool/lpd
[...]
$

script3.gawk 程序脚本定义了一个变量来保存 print 命令中用到的文本字符串。注意,gawk 程序在引用变量值时并未像 shell 脚本一样使用 $.

6. 在处理数据前运行脚本

gawk 还允许指定程序脚本何时运行。默认情况下,gawk 会从输入中读取一行文本,然后针对该行的数据执行程序脚本。有时可能需要在处理数据前运行脚本,比如为报告创建标题。BEGIN 关键字就是用来做这个的。它会强制 gawk 在读取数据前执行 BEGIN 关键字后指定的程序脚本。

$ gawk 'BEGIN {print "Hello World!"}'
Hello World!
$

这次 print 命令会在读取数据前显示文本。但它在显示了文本后会快速退出,不等待任何数据。如果想使用正常的程序脚本处理数据,必须用另一个脚本区域来定义程序。

$ cat data3.txt 
Line1
Line2
Line3
$
$ gawk 'BEGIN {print "The data3 File Contents:"} {print $0}' data3.txt 
The data3 File Contents:
Line1
Line2
Line3
$

7. 在处理数据后运行脚本

与 BEGIN 关键字类似,END 关键字允许你指定一个程序脚本,gawk 会在读完数据后执行它。

$ gawk 'BEGIN {print "The data3 File Contents:"}
> {print $0}
> END {print "End of File"}' data3.txt
The data3 File Contents:
Line1
Line2
Line3
End of File
$

当 gawk 程序打印完文件内容后,它会执行 END 脚本中的命令。这是在处理完所有正常数据后给报告添加页脚的最佳办法。

$ cat script4.gawk 
BEGIN {
    print "The latest list of users and shells"
    print " UserID \t Shell"
    print "-------- \t -------"
    FS=":"
}
{
    print $1 "         \t " $7
}
END {
    print "This concludes the listing"
}
$

这个脚本用 BEGIN 脚本来为报告创建标题。它还定义了一个叫做 FS 的特殊变量。这是定义字段分隔符的另一种方法。这样你就不用依靠脚本用户在命令行选项中定义字段分隔符了。

$ gawk -f script4.gawk /etc/passwd
The latest list of users and shells
 UserID          Shell
--------         -------
root             /bin/bash
daemon           /usr/sbin/nologin
bin              /usr/sbin/nologin
sys              /usr/sbin/nologin
sync             /bin/sync
[...]
sshd             /usr/sbin/nologin
pollinate                /bin/false
mary             /bin/bash
This concludes the listing
$
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值