Chinaunix首页 | 论坛 | 博客
  • 博客访问: 417386
  • 博文数量: 120
  • 博客积分: 3125
  • 博客等级: 中校
  • 技术积分: 1100
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-29 10:59
文章分类

全部博文(120)

文章存档

2012年(28)

2011年(22)

2010年(34)

2009年(1)

2008年(35)

我的朋友

分类: LINUX

2008-11-21 16:28:11

SED,AWK学习笔记Part 2-----sed编辑器

在 unix系统下,sed,awk,ex,ed,vi,grep以及egrep等等有着极为重要的作用,它们强大的文本处理功能使他们经过这几十年的使用还 仍然是大多数人的宠儿。本文是通过阅读一本英文版sed和awk的学习手册手译的笔记,希望通过读这本书能更加熟练地使用这些工具。

这是第 二部分,祥细地介绍了sed编辑器的使用方法。

1.4 Sed编辑器
sed 是一个非交互式的流编辑器.它解释了一段脚本并执行脚本中的操作。sed是面向流的,因为跟很多的unix程序一样,它的程序输入是通过输入流的,并且它 是直接输出到标准的输出的。例如sort是面向流的,但vi就不是。sed的输入经常是来自于一个文件或一个管道,但是它也可以从键盘中重定向过去。输出 会默认的会输出的屏幕上,但是可以被捕捉到一个文件中或是发送到一个管道里。

对于sed通常的用法有:

1. 自动地编辑一个或多个文件
2. 对多个文件的重复性操作进行简化。
3. 编写转换程序

sed是像如下方式运行的:
1. 输入的每一行都被拷贝到模式空间中,一个进行编辑操作的中间缓冲器
2. 在一个sed的脚本中的所有的编辑命令都会被按顺序地通输入的每一行进行操作
3. 编辑命令会被应用到所有的行上,除非对处理范围进行限定。
4. 如果一个命令改变了输入,那么后续的命令和地址测试会被应用到当前行中,还不是初始的输入行中
5. 因为编辑命令改变了原始输入行的一个拷贝,那么原始的输入文件没有被进行更改。这个拷贝会被送到标准输入中(而不是重定向到一个文件中)
6. sed会维持着保留的空间,一个分离缓冲会被除数用来为以后的读取存储数据.

1.4.1 命令行语法
sed的调用有以下两种形式:

sed [-n][-e] 'command' file(s)
sed [-n] -f scriptfile file(s)

第一种形式让你可以指定一个编辑命令,用引号引起来。第二种形式可以让你指定一个脚本文件,一个包含sed命令的文件。这两种形式会共同使用,他们可能会被使用多次。如果没有文件被指定,那么sed会从标准输入读取。

以下的参数被认为是:

-n
 关闭默认输出,sed会只显示那些用p命令或是s命令中有p标志的行。
-e cmd
 下一个参数是一个编辑命令。如果多个脚本或多个命令被使用的时候比较有用。
-f file
 下一个参数是一个包含编辑命令的脚本文件。

如果脚本的第一行是#n,则sed会表现的像-n参数被使用过一样。

1.4.2 sed命令的语法

sed命令有一个通用的形式:
[address[,address]][!]command [arguments]
sed 会把输入的每一行拷贝到模式空间中,sed指令由一系列的地址跟编辑命令构成。如果命令的地址跟在模式空间中的行一样的话,那么命令就被执行到这一行上。 如果一个命令没有地址,那么它就会被应用到每一行中。如果一个命令改变了模式空间的内容,那么后续的命令会应用到模式空间的当前行中,而不是原始文件的输 入行。

地址在下一节中会被描述出来。命令是由一个字母或一个符号构成,它们会在下面被描述,按字母序被分类。参数包括b或t命令的标签,r或w的文件名,以及s命令的替换标记。

1.4.2.1 模式地址
一 个sed命令可以指明0个,一个或两个地址,一个地址可以是一个行号,符号$或一个用反斜扛括起来的正则表达式.正则表达式在1.3节被描述过了(见 sed awk学习笔记part1)。另外,n可以被匹配模式空间的任何一个新行(由N命令造成的),但是不是在模式空间结束部分的新行。

如果命令指定了:0个地址,那么命令应用到所有的输入行。
如果命令指定了:1个地址,那么命令应用到任何匹配的地址行。一些命令只接收一个地址,如:a,i,r,q和=.
如果命令指定了:两个用逗号分开的地址,那么命令应用到第一个匹配的行以及所有的之后的并包第二个地址的行。
如果命令指定了:一个后接!的地址,那么命令会被应用到所有不匹配的行上。

1.4.2.2 例子
命令: s/xx/yy/g
功能:在所有的行上做替换。

命令:/BSD/d
功能:删除所有有BSD的行

命令:/^BEGIN/,/^END/p
功能:打印BEGIN和END之间的内容,包括这两行。

命令:/SAVE/!d
功能:删除所有不含SAVE的行

命令:/BEGIN/,/END/!s/xx/yy/g
功能:除去在BEGIN和END的部分,在所有的行上做替换。

括号(())在sed中被用来把一个地址嵌到另一个地址中或是用来对匹配的同样的址应用多个命令.

[/pattern/[,/pattern/]]  {
command1
command2
}
开大括号必须结束这一行,闭大括号必须自用一行。请确定在括号后面没有空格。

1.4.3 sed命令的总结

下列的列表中,sed命令以函数分类被简洁地描述出来。完整的描述,包挺语法和例子可以在后面的1.4.4节找到。

1.4.3.1 基本的编辑命令:

a 在一行后加文字
c 替换文本(常是一个文本块)
i 在一行前插入文本
d 删除行
s 做替换
y 转换字符(就像unix里面的tr)

1.4.3.2 行信息
= 显示行号
l 用ASCII码显示控制符
p 显示这一行


1.4.3.3 输入输出处理
n 跳过这一行到下一行
r 从另一个文件中读取内容到输出流中
w 把输入行写到另一个文件中
q 退出sed脚本(没有其他的输出).

1.4.3.4 拉和放
h 拷贝到保留空间中,覆盖原先有的内容。
H 拷贝到保留空间中,追加到原先有的内容后
g 取回保留空间,消除目标行
G 取回保留空间,追加到模式空间中
x 交换保留空间和模式空间中的内容

1.4.3.5 分支命令
b 分支到标志或脚本的结束处
t 与b命令知道,但是只在替换后进行分支操作。
:label 由t或b分支的标记

1.4.3.6 多行输入的处理
N 读入另一个输入行(创建一个嵌入的新行)s
D 删除嵌入行
P 打印嵌入行

1.4.4 sed命令的字母序总结

#:在一个sed脚本中开始注释。只在一行的第一个字符有效。(一些版本允许在任何地方进行注释,但是最好不要依赖这一点.)如果一个脚本的第一行是#n,那么sed会表现得像-n参数被使用了

:label:  在脚本中标记一行被用来由b或t命令交换控制。标记最多可以容许有7个字符

=: [/pattrern/]=向标准输出流写出由模式标识的每一行

a: [address]a text 在匹配的地址中追加下列文本。如果文本超过了一行,那么新行必须是隐藏的,是由反斜扛来引导的。文本由第一个不由这样的隐藏方式的新行结束.文本在模式空 间中不是有效的,后续的命令不能被应用到它上面。这个命令的结果当编辑命令结束的时候被发送到标准的输出流中,而不考虑在模式空间中对于当前行发生了什么 事。

b: [address1[,address2]]b[label]无条件地转移到在脚本中另一处的:label标记,也就是,在label后接的命令是对当前行应用的下一条命令。如果没有指定任何标记,控制跳到脚本的最后,这样就没有其他命令可以被应用到当前行上。

c: [address1[,address2]]ctext 替换由文本地址选定的行。当一个范围的行被指定后,所有的行都以一组或一个单独的文本拷贝进行替换。模式空间的内容被删掉了后续的编辑命令会被应用到模式空间(或文本)中

d: [address1[,address2]]d 从模式空间中删除地址行(或多行)。这样,这一行就不会被传输到标准输出中,一个输入的新行被读入,且编辑恢复到脚本的第一个命令上

D: [address1[,address2]]D 删除模式空间中的由N命令生成的多行的第一部分,并恢复到脚本的第一行.如果这个命令清空了模式空间,输入的一个新行就被读入,就像d命令被执行了一样。

g: [address1[,address2]]g 把保留空间的内容粘贴回(见h和H命令)到模式空间中,清除模式空间之前的内容

G: [address1[,address2]]G 与g相同,不同点在于一个新行和保留空间被追加到模式空间后面而不是覆盖掉.
 
h: [address1[,address2]h 把模式空间中的内容拷贝回保留空间中,一种特殊的临时性的缓冲.保留空间中的前面的内容被删掉。你可以使用h命令来在编辑这行之前先保存它。

H: [address1[,address2]H 加一个新行并加模式空间的内容到保留空间中。甚至当你保留空间是空的H仍然加一个新行,H就像是一个增量拷贝.

i: [address]itext 在地址匹配的一行前插入文本

l: [address1[,address2]]l 列出模式空间中的内容,用ASCII码显示非打印字符。长号会被折叠处理。

n: [address1[,addresw2]]n  从输入的下一行到读到模式空间中。当前行被送到标准输出中,下一行成为当前行。控制转到后面的n命令而不是恢复到脚本的最顶部

N: [address1[,address2]]N 把下一个输入行追加到模式空间;新行与模式空间的前面的内容相分离.(这个命令的设计是为了允许在两行间进行模式匹配)通过使用n来配一个嵌入的新行,你可以在很多行中匹配模式。

p: [address1[,address2]]p 打印地址行。注意这可以造成重复输出,除非默认的输出由#n或-n命令号参数关闭了。经常用在命令之前用来改变流控制(d,b,n),这样会防止当前行被输出。

P: [address1[,address2]]P 打印用N命令生成的多行模式空间的第一部分。当N没有被应用到这一号时与p相同

q: [address]q 当遇到地址时退出。地址的行被先与在之后用a或r命令追加的任何文本写到输出(如果默认的输出没有被关闭),

r: [address]r file 把文件内容读出,并加到模式空间的后面。必须在r和文件名之间仅有一个空格

s: [address1[,addres2]]s/pat/repl/[flags] 在地址行把repl用pat代替。如果模式地址被用到了,那么模式//表示最后一个地址指定的模式.任何的发界符都被应用了。在pat或repl中用来退 出分界符。下面的标记可以被申明:
        n: 在每一个地址行上替换pat的第n个实例。n可以是从1到512的任意数字,默认为1
        g: 在每一个地址行中替换pat的所有实例,而不只是第一个实例
        p: 如果替换成功的话,打印这个号码,如果多个替换成功的话,sed会打印多个号的拷贝。
        w: file 如果一个替换被执行了,把这一行写到一个文件中,最多可以打开10个文件

t: [address1[,address2]]t [label] 测试在地址行上替换能不能被成功地执行,如果可以的话,跳到:label处.如果label没有被申明,则控制会跳到脚本的最底部。t命令就像C语言里面 的case一样的或是其他所有的shell语言。你测试这个case,如果它是无休止的,你退出这个结构体

w: [address1[,address2]]w file 把模式空间的内容加到一个文件中,如果当命令运行了而不是模式空间被输出了,这个操作被执行。在w和文件名之后有且仅有一个空格。最多可以打开10个不同 的文件。这个命令会在文件不存在的时候生成一个文件。如果文件存在的话,它的内容会被脚本执行的每一次被覆盖掉。多个把输出定向到一个文件的写命令会会把 内容添加到文件的结束部分

x: [address1[,address2]]x 把模式空间与保留空间的内容进行交换。

y: [address1[,address2]]y/abc/xyz/ 传递字符.把a转为x,b转为y,c转为z等等

阅读(767) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~