您的位置:首页 > 其它

揭开sed和awk的秘密

2011-12-30 16:33 351 查看
如果你经常使用正则表达式(regular expression),那么一定熟悉UNIX的两个文本工具:sed和awk。

这两个工具很易学,而且都对模式匹配(patten match*译者注:这里的意思应该是给定若干的条件,对符合条件的对象进行预定的处理,也可以说是条件匹配*)很有用。Sed是流编辑器;它由命令 simple ed得名;awk是一种编程语言,它的名字是它的三个开发者名字(Aho、Weinberger和Kernighan)的首字母组合得到的。我将在本文中 介绍sed和awk的基本知识,进一步的知识将在以后的几篇文章中阐述。

Sed和awk都很胜任自动单调的(automating monotonous)文本编辑任务,该任务一般在文本编辑器用交互方式完成的。Sed和awk都是基于流的,也就是说它们的输入来自文本文件中——一次得到一行——然后产生标准输出。

Sed 主要用于对单个或多个文件的重复编辑。Awk,做为一种编程语言,可以用来处理结构化的数据,然后产生格式化的报告。Sed和awk都可以像外壳脚本 (shell script)那样被执行;每一个动作都是顺序运行的。Sed脚本通常用于简单任务,如完成条目(如从一个或者一系列文件中获取的方法的名字)的连接。 Awk更适合完成复杂的任务,如重新格式化数据或建立定制报告(custom report)。

Awk是一个完整的编程语言,它的作用不限于sed那样的文本编辑器。Awk擅长从系统记录(system log)或来自数据库(该数据库基于文本)的数据来生成报告。然而,为了发挥awk的用处,数据必须是结构化的,这是awk本身所决定的。

表A

sed

awk

Double/triple-space a file

转化DOS/UNIX 的新行(newline)

删除前后的空格

在所有/全部行上进行取代操作

删除连续的空行

删除文件开头和结尾的空行

管理小的、个人的数据库

产生报告

验证数据

生成下标、执行其它文档预备任务

试验算法,这些算法稍后可以由其它语言实现

处理UNIX命令的结果

更合理地处理命令行的参数

Sed和awk的常见用法

Sed与awk使用类似的语法,这就简化了对它们的学习过程。Sed程序由命令行组成,而awk程序是由编程语句和函数组成的。

Sed的运行过程

我们已经提到,sed脚本是顺序执行的。首先,模式匹配上了,程序就开始运行。然后,对输入文件的当前行运行脚本文件,每运行脚本文件的一行,都产生相应的输出。但脚本中的所有命令行都执行完了之后,sed开始对对输入文件的下一行开始执行脚本中的指令。

你可以在UNIX的命令行中这样调用sed:

#sed [选项] 脚本文件/命令输入文件

下面以一个记载联系方式的名为phonelist.txt文件为例,介绍sed的用法。记录中包括姓名、家庭电话、宿舍电话和E-mail地址:

John Doe, 100-555-1111, 100-555-1112,

Jane Doe, 100-555-2222, 100-555-1113,

Jimmy Dean, 101-555-1111, 101-555-2222,

让我们首先看看比较简单的sed编辑命令:

$sed ‘s/100-/(100) /’ phonelist.txt

该命令将把区号为100的第一个电话号码从xxx-xxx-xxxx格式转换到(xxx) xxx-xxxx格式。

如果我们想对所有的区号为100的电话号码都做上述格式转换,就需要使用/g选项。

$sed ‘s/100-/(100) /g’ phonelist.txt

该操作作用于输入文件的所有的行。我们也可以在一个命令行上执行多个指令,这可以通过使用-e选项,也可以用分号(;)来分隔命令,如:

$sed –e ‘s/100-/(100) /g’-e ‘s/101-/(101) /g’ phonelist

$sed ‘s/100-/(100) /g’; ‘s/101-/(101) /g’ phonelist

(* 译者注:注意要把输入文件的行和命令行区分开来,前者在本例中指得是文件phonelist.txt的某一行,如“John Doe, 100-555-1111, 100-555-1112, ”,后者指的是sed用户在敲入UNIX的命令行或者sed脚本文件中的某一行。*)

当需要使用多个命令时,用脚本文件也许更加合适。脚本文件的格式很简单——一行写一条命令:

$sed –f scriptfile inputfile

我们可以用外壳重定向(shell redirect)来把输出保存到文件中。

还有一个常用选项是-n,它专门用于限制命令行是否产生输出。使用-n选项后,只有末尾有“/p”选项的命令行才产生输出,如:

$sed –n ‘s/pattern/substitute/p’ inputfile

该命令将会只输出输入文件改变的部分。

Awk的运行过程

Awk也可以用命令行或者脚本文件的方式处理单个或者多个文件:

$awk ‘指令’ 输入文件

$awk –f 脚本文件输入文件

Awk将每一行分解为记录,用空格或者制表符来区分记录中的字段。它允许在任何过程中以任何方式访问这些字段。$0表示整个记录(行),$1、$2、……指向输入行的各个字段。

如果没有指定模式,则使用默认模式,即整个输入文件。如:

$awk ‘{ print $1}’ phonelist.txt

就会输出如下结果:(整个输入文件的$1字段都输出来了)

John

Jane

Jimmy

如果没有给定处理过程,就使用默认处理print(打印),如:

$awk ‘/Jane/’ phonelist.txt

将会输出:

Jane Doe, 100-555-2222, 100-555-1113,

正式用法是同时指定匹配模式和处理过程。让我们用下面这条命令来输出Jane的家庭电话号码:

$awk ‘/jane/ { print $3}’ phonelist

这会输出:

100-555-2222

我们可以通过用-F选项来选定任何我们喜欢的间隔符。因为我们的输入文件phonelist是用逗号来分隔的,所以我们需要用逗号来做分隔符。

命令如下:

$awk –F, ‘{print $1}’ phonelist.txt

这条命令将会输出下列名字:

John Doe

Jane Doe

Jimmy Dean

如果我们想格式化输出姓氏和名字,我们可以这么做:

$awk –F, ‘{print $2 $1}’ phonelist.txt

结果是:

Doe, John

Doe, Jane

Dean, Jimmy

为了达到一行只输出一个字段的目的,我们可以用分号去分开打印语句,如:

$awk -F, '{ print $1; print $2; print $3; print $4 }' phonelist.txt

结果就会这样:

John Doe

100-555-1111

100-555-1112

Jane Doe

100-555-2222

100-555-1113

Jimmy Dean

101-555-1111

101-555-2222

现在总结一下,sed主要用来改变数据;awk用来重新排列数据。通过sed和awk的高级编程可以采集到大量的信息。

http://www.newsmth.net/pc/pccon.php?id=2207&nid=82422
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: