sed实例解析
时间:2008-05-17 来源:poplar.xu
前面我们已经列出了sed中经常用到的命令,下面我们就用实例介绍各个命令的用法。首先我们先打印出讲解这些例子时用到的一个文件:
cat students
Paris PS1 Charles Chin 01/20/86 30
Indian Ocean PS2 Susan Green 04/05/86 32
SUST PS2 Lewis Gray 08/11/85 23
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35
Paris IS3 Peter Webor 07/05/82 32
Paris PS2 Ann Sreph 09/28/85 10
Paris IS3 Margot Strong 02/29/82 9
6.1 打印命令:p
sed ‘/HEBUT/p’ students
Paris PS1 Charles Chin 01/20/86 30
Indian Ocean PS2 Susan Green 04/05/86 32
SUST PS2 Lewis Gray 08/11/85 23
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35
Paris IS3 Peter Webor 07/05/82 32
Paris PS2 Ann Sreph 09/28/85 10
Paris IS3 Margot Strong 02/29/82 9
默认情况下,sed将每个输入的行都打印一遍,如果在某一行中匹配到了HEBUT,就将该行另外打印一遍。
sed –n ‘/HEBUT/p’ students
HEBUT IS1 John Main 12/03/84 8
这个例子用-n取消了默认的打印,只有匹配到HEBUT的行才打印出来。
6.2 指定行的范围
sed –n ‘4p’ students
JUST IS1 Xiao Ming 11/30/84 9
只打印第四行。
sed –n ‘4!p’ students
Paris PS1 Charles Chin 01/20/86 30
Indian Ocean PS2 Susan Green 04/05/86 32
SUST PS2 Lewis Gray 08/11/85 23
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35
Paris IS3 Peter Webor 07/05/82 32
Paris PS2 Ann Sreph 09/28/85 10
Paris IS3 Margot Strong 02/29/82 9
除了第四行外都打印。
sed –n ‘1,2p’ students
Paris PS1 Charles Chin 01/20/86 30
Indian Ocean PS2 Susan Green 04/05/86 32
打印第1到第2行。
sed –n ‘3,/^HEBUT/p’ students
SUST PS2 Lewis Gray 08/11/85 23
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
从第3行开始打印,一直到第一个以HEBUT开头的行结束。如果找到文件末尾都没有找到以HEBUT开头的行,则打印到文件最后一行结束。
sed –n ‘/JUST/,/SUST/p’ students
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35
从第一个出现JUST的行开始打印,直到从这一行开始,第一次出现SUST的行。如果直到文件末尾都没有出现SUST,则打印到文件末尾结束。
p命令打印的是模式空间中的内容,而不是原文件中的内容。也就是说,如果在打印命令p之前有命令将模式空间中的内容修改了(比如执行了替换命令),p命令打印的将是修改后的内容。
6.3 删除命令:d
sed ‘$d’ students
Paris PS1 Charles Chin 01/20/86 30
Indian Ocean PS2 Susan Green 04/05/86 32
SUST PS2 Lewis Gray 08/11/85 23
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35
Paris IS3 Peter Webor 07/05/82 32
Paris PS2 Ann Sreph 09/28/85 10
删除最后一行。美元符号$表示最后一行,默认情况下,除了最后一行外其他各行都被打印出来。不要混淆地址范围中的$和正则表达式中的$!
sed ‘4,$d’ students
Paris PS1 Charles Chin 01/20/86 30
Indian Ocean PS2 Susan Green 04/05/86 32
SUST PS2 Lewis Gray 08/11/85 23
删除第四行到最后一行。
6.4 替换命令:s
替换命令的格式为:
s/regexp/replacement/flag
其中regexp是一个正则表达式,该命令将用replacement替换由regexp匹配到的内容。flag是替换命令的选项,功能如下
flag |
功能 |
g |
进行全局替换。不使用此选项将只对该行匹配到的第一个结果进行替换 |
p |
打印模式空间中的内容(替换之后的内容) |
w filename |
将替换之后的内容写入文件filename |
flag可以没有,但它前面的斜线不能丢掉。
sed –n ‘s/SUST/SDUST/gp’ students
SDUST PS2 Lewis Gray 08/11/85 23
SDUST PS2 Da Ming 06/01/86 35
将所有SUST替换为SDUST,并将替换后的行打印出来。
sed ‘s/[0-9][0-9]$/&.5/’ students
Paris PS1 Charles Chin 01/20/86 30.5
Indian Ocean PS2 Susan Green 04/05/86 32.5
SUST PS2 Lewis Gray 08/11/85 23.5
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35.5
Paris IS3 Peter Webor 07/05/82 32.5
Paris PS2 Ann Sreph 09/28/85 10.5
Paris IS3 Margot Strong 02/29/82 9
将所有以两位数字结尾的行的后面加上一个.5。&符号用在替换串中时,代表查找串中匹配到的内容。如果替换串中要用到&的字面含义,就要用反斜线将其转义,如 \&。
替换命令s后面不仅可以跟斜线作为分隔符,其他任意字符都可以,这在处理含有斜线的行(比如含日期的行)是非常有用的,例如:
sed ‘s#02/29/82$#02/29/83#g’ students
Paris PS1 Charles Chin 01/20/86 30.5
Indian Ocean PS2 Susan Green 04/05/86 32.5
SUST PS2 Lewis Gray 08/11/85 23.5
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35.5
Paris IS3 Peter Webor 07/05/82 32.5
Paris PS2 Ann Sreph 09/28/85 10.5
Paris IS3 Margot Strong 02/29/83 9
这里s后面的分隔符可以是任意字符,但要保证s命令其余的两个分隔符也是这个符号。
6.5 读取文件命令r和写入文件命令w
cat newfile
|-----------------------------------------------------------------------------|
|** IS3 students have already graduated from SUPINFO **|
|-----------------------------------------------------------------------------|
sed ‘/IS3/r newfile’ students
Paris PS1 Charles Chin 01/20/86 30.5
Indian Ocean PS2 Susan Green 04/05/86 32.5
SUST PS2 Lewis Gray 08/11/85 23.5
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35.5
Paris IS3 Peter Webor 07/05/82 32.5
|-----------------------------------------------------------------------------|
|** IS3 students have already graduated from SUPINFO **|
|-----------------------------------------------------------------------------|
Paris PS2 Ann Sreph 09/28/85 10.5
Paris IS3 Margot Strong 02/29/82 9
|-----------------------------------------------------------------------------|
|** IS3 students have already graduated from SUPINFO **|
|-----------------------------------------------------------------------------|
如果在文件students的某一行找到模式IS3,就读取文件newfile的内容并放在该行的后面。如果找到了多个匹配的行,则在每一行的后面都插入文件newfile的内容。
sed ‘/IS3/w newfile’ students
Paris PS1 Charles Chin 01/20/86 30
Indian Ocean PS2 Susan Green 04/05/86 32
SUST PS2 Lewis Gray 08/11/85 23
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35
Paris IS3 Peter Webor 07/05/82 32
Paris PS2 Ann Sreph 09/28/85 10
Paris IS3 Margot Strong 02/29/82 9
cat newfile
Paris IS3 Peter Webor 07/05/82 32.5
Paris IS3 Margot Strong 02/29/82 9
将文件students中所有匹配模式IS3的行写入文件newfile,如果newfile不存在,则创建newfile,若newfile已存在,则覆盖newfile。
6.6 追加命令:a
sed ‘/Xiao Ming/a\ ---->Xiao Ming is from JUST. ’ students
Paris PS1 Charles Chin 01/20/86 30
Indian Ocean PS2 Susan Green 04/05/86 32
SUST PS2 Lewis Gray 08/11/85 23
JUST IS1 Xiao Ming 11/30/84 9
---->Xiao Ming is from JUST.
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35
Paris IS3 Peter Webor 07/05/82 32
Paris PS2 Ann Sreph 09/28/85 10
Paris IS3 Margot Strong 02/29/82 9
每当匹配到Xiao Ming,就另起一行并添加---->Xiao Ming is from JUST. 。如果要添加的内容中含有换行符,需要将换行符用反斜线转义。例如下面的例子:
sed ‘/Xiao Ming/a ---->Xiao Ming is from JUST. \
He is in the SIS SSN team. <-----’ students
Paris PS1 Charles Chin 01/20/86 30
Indian Ocean PS2 Susan Green 04/05/86 32
SUST PS2 Lewis Gray 08/11/85 23
JUST IS1 Xiao Ming 11/30/84 9
---->Xiao Ming is from JUST.
He is in the SIS SSN team. <-----
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35
Paris IS3 Peter Webor 07/05/82 32
Paris PS2 Ann Sreph 09/28/85 10
Paris IS3 Margot Strong 02/29/82 9
在这个例子中我们需要在匹配到Xiao Ming的行的后面插入两行,如果在命令中直接敲入回车换行符,sed会 想当然地认为这是命令的结束而报错。因此,在命令多于一行的情况下,要用反斜线将换行符转义。实际上,当我们敲击键盘上的回车键时,我们实际上是键入了一 个特殊字符——换行符,这是一个不可见的字符,体现在计算机屏幕上就是换行符后面的文字在下一行上显示。也就是说,换行符也是一个字符,只不过是个特殊字 符,因此它可以像普通字符一样使用,只不过使用它时要特别小心,因为换行符在shell中通常用作表示命令的结束,当我们不希望它表示命令的结束的时候,我们就要用一个反斜线将其转义。这就像在c语言中一样,我们可以将较长的代码用反斜线分成多行。因为UNIX是用c语言编写的,UNIX中的大多数命令也是用c语言编写的,所以UNIX中命令的格式很多地方很像c语言。例如在上面的例子中,我们可以不用反斜线将回车换行符转义,而直接用\n代表换行符,将整条命令写在一行上。写作:sed ‘/Xiao Ming/a ---->Xiao Ming is from JUST. \nHe is in the SIS SSN team. <-----’,结果和上面的例子是一样的。
6.7 插入命令:i
sed ‘/Xiao Ming/i\ -----------------------------------------------------------------------’ students
Paris PS1 Charles Chin 01/20/86 30
Indian Ocean PS2 Susan Green 04/05/86 32
SUST PS2 Lewis Gray 08/11/85 23
-----------------------------------------------------------------------
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35
Paris IS3 Peter Webor 07/05/82 32
Paris PS2 Ann Sreph 09/28/85 10
Paris IS3 Margot Strong 02/29/82 9
在这个例子里,命令i用来在匹配到JUST的行的前一行插入一条分割线。
6.8 下一行命令:n
sed ‘/SUST/{n; s/Peter/PETER/; }’ students
Paris PS1 Charles Chin 01/20/86 30
Indian Ocean PS2 Susan Green 04/05/86 32
SUST PS2 Lewis Gray 08/11/85 23
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35
Paris IS3 PETER Webor 07/05/82 32
Paris PS2 Ann Sreph 09/28/85 10
Paris IS3 Margot Strong 02/29/82 9
我们来看一下这个命令的执行过程。首先sed匹配到含有SUST的行,并将其装入模式空间,然后sed读到了n命令,于是sed将模式空间里的那一行的下一行(即含有Peter Webor的那一行)装入模式空间并替代掉模式空间里以前的内容,然后对模式空间里的这一行从命令n的下一条命令开始对其进行处理,处理完毕后,sed将打印处理后的那一行,并从被处理过的那一行(即含有Peter Webor的那一行)的下一行开始继续进行新一轮的处理。
6.9 y 命令
sed ‘1,2y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/’ students
PARIS PS1 CHARLES CHIN 01/20/86 30
INDIAN OCEAN PS2 SUSAN GREEN 04/05/86 32
SUST PS2 Lewis Gray 08/11/85 23
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35
Paris IS3 PETER Webor 07/05/82 32
Paris PS2 Ann Sreph 09/28/85 10
Paris IS3 Margot Strong 02/29/82 9
将前两行中所有的小写字母换为大写字母。替换是对应的,而且y命令中不能用正则表达式,因此不能写成sed ‘1,2y/[a-z]*/[A-Z]*/’。
6.10 暂存命令h 和取用命令g
h命令将将模式空间里的内容拷贝到暂存缓冲区并替换原来暂存缓冲区的内容,而g命令将里暂存缓冲区的内容拷贝到模式空间并替换原来模式空间的内容。
sed –e ‘/JUST/h’ –e ‘$g’students
Paris PS1 Charles Chin 01/20/86 30
Indian Ocean PS2 Susan Green 04/05/86 32
SUST PS2 Lewis Gray 08/11/85 23
JUST IS1 Xiao Ming 11/30/84 9
HEBUT IS1 John Main 12/03/84 8
SUST PS2 Da Ming 06/01/86 35
Paris IS3 Peter Webor 07/05/82 32
Paris PS2 Ann Sreph 09/28/85 10
JUST IS1 Xiao Ming 11/30/84 9
第一个命令将首先匹配含有JUST的行,当然sed会将其装入模式空间,然后将模式空间的内容复制到暂存缓冲区并替换原来暂存缓冲区的内容。然后sed执行第二条命令,sed将找到最后一行,当然sed会将最后一行装入模式空间,然后将暂存缓冲区的内容复制到模式空间并替换原来模式空间的内容。经过这样的处理,含有JUST的行被复制并替换了最后一行。
H命令和G命令与h和g命令的唯一不同是H和G是H将模式空间里的内容追加到暂存缓冲区,G将暂存缓冲区里的内容追加到模式空间。