正则表达式之awk
时间:2008-09-23 来源:落魄剑客
本教程首先对正则表达式进行了基本的解释,然后介绍了 grep 和 sed。grep 是一个强大的搜索实用程序,而 sed 则是一个更加强大的搜索和替换实用程序。awk 则更进一步,它在全功能的命令行编程语言中使用正则表达式。正如 sed 一样,当在命令行上使用 awk 时,它接受基于行的输入。awk 一次解释一行输入,但是与 sed 不同,它将该行上的每个部分作为变量来处理,这些变量可用作内联代码的输入和输出。
应该指出的是,AWK(大写)是一个可用于编写脚本(而不只是在命令行上使用)的全功能编程语言,但本教程集中于 awk,后者是动态解释 AWK 命令的命令行实用程序。
顺便提一下,任何人阅读到这里都会考虑如何实际运用所学到的知识,我刚才就使用 grep 在某些旧代码中搜索理想的 awk 示例:
grep awk */*.pl |
大多数系统管理员或程序员每天都会看到这些工具的应用。下面是我的输出中的一些行:
Edaemon/m_checkcurrentdisk.pl:$freespace = `awk '(NR==1) {print \$4 / 1024 / 1024}' grep.tmp`; Edaemon/m_getdatetime.pl:$month = `awk '(NR==1) {print \$2}' datetime.txt`; Odaemon/odaemon.beowulf.dvd.pl:$filesize = `awk '(NR==1) {print \$1}' temp.txt`; |
这些是非常好的示例,因为它们说明了非常基础的 awk 应用。对于您的第一次尝试,甚至可以使它更简单。对于您的 awk 测试,请在一个空目录中创建以下文件(每个文件的内容无关紧要,并且它们可以是空的)。
Screenshot_1.jpg Screenshot_2.jpg Screenshot_3.jpg awk.txt regular.txt sed.txt |
缺省情况下,awk 读取输入文件中的每一行,并将内容分离为由空格确定的变量。在非常简单的示例中,您可以使用 ls 的输出作为 awk 的输入并打印结果。此示例结合使用管道字符 (|) 和 ls 来将输出发送到 awk:
ls | awk ' { print $1 } ' |
awk 随后打印每行上的第一项,在此例中为每行上的唯一项:
Screenshot_1.jpg Screenshot_2.jpg Screenshot_3.jpg awk.txt regular.txt sed.txt |
这确实是非常基本的功能。对于下一个示例,请使用 ls -l 来为 awk 生成多列输入:
ls -l |
不同系统的 ls 实现稍有差别,下面是一些示例输出:
total 432 -rw-rw-rw- 1 guest guest 169074 Oct 15 14:51 Screenshot_1.jpg -rw-rw-rw- 1 guest guest 23956 Oct 15 20:56 Screenshot_2.jpg -rw-rw-rw- 1 guest guest 12066 Oct 15 20:57 Screenshot_3.jpg -rw-r--r-- 1 tuser tuser 227 Oct 15 20:16 awk.txt -rw-r--r-- 1 tuser tuser 233 Oct 15 19:35 regular.txt -rw-r--r-- 1 tuser tuser 227 Oct 15 23:16 sed.txt |
请注意,文件所有者是每行上的第三个项,文件名是每行上的第九个项(缺省情况下,awk 中的项之间用空格分隔)。通过打印每行上的第三和第九个变量,您可以使用 awk 来从该列表提取文件所有者和文件名。下面是完成这项工作的命令:
ls -l | awk ' { print $3 " " $9 } ' |
您将注意到,awk 中的 print 命令有两个引号,而且引号中有一个空格。这只是为了在输出的文件所有者和文件名之间打印一个空格:
guest Screenshot_1.jpg guest Screenshot_2.jpg guest Screenshot_3.jpg tuser awk.txt tuser regular.txt tuser sed.txt |
您可以在 awk 打印语句中的变量之间的引号中放置任何文本。
现在您已经学习了如何使用 awk 的基础知识,但本教程不是关于正则表达式的吗?awk 中大量使用了正则表达式。最常见的示例是在 awk 命令前附加一个正则表达式,用于指定您想要操作的行。与 sed 一样,awk 中的正则表达式位于两个正斜杠之间。例如,如果您只希望操作 tuser 所拥有的文件,则可以使用以下命令:
ls -l | awk ' /tuser/ { print $3 " " $9 } ' |
该命令产生以下输出:
tuser awk.txt tuser regular.txt tuser sed.txt |
在另一个示例中,您可能希望更改每个文本文件的文件扩展名而不更改图像文件。为此,您将需要使用句点而不是空格来分隔输入变量,然后使用正则表达式来指示您仅希望搜索文本文件。若要基于句点来分隔变量,可以使用 -F 标志,后跟后跟您希望使用的字符(用引号引起来)。尝试此示例,通过管道将 awk 输出发送到某个 Shell(此 Shell 将执行 awk 生成的命令):
s | awk -F"." ' /txt/ { print "mv " $1 "." $2 " " $1 ".doc" } ' | bash |
后续的 ls -l 将显示新的文件名:
-rw-rw-rw- 1 guest guest 169074 Oct 15 14:51 Screenshot_1.jpg -rw-rw-rw- 1 guest guest 23956 Oct 15 20:56 Screenshot_2.jpg -rw-rw-rw- 1 guest guest 12066 Oct 15 20:57 Screenshot_3.jpg -rw-r--r-- 1 tuser tuser 227 Oct 15 20:16 awk.doc -rw-r--r-- 1 tuser tuser 233 Oct 15 19:35 regular.doc -rw-r--r-- 1 tuser tuser 227 Oct 15 23:16 sed.doc |
记住,这些只是 awk 的入门基础知识,但是 AWK 是一种全功能的编程语言,所具有的功能远远超出了本教程所介绍的内容。请查看一下 awk man 页。如果您希望学习更多的知识,花钱买一本优秀的图书是明智的。