掌握Sed命令


带书签PDF版,喜欢的话,欢迎多提意见和建议,你的支持是血蝙蝠最大的前进动力!


http://download.csdn.net/detail/challenge_c_plusplus/6480007


 

 

Part0    Sed预备知识

0.1 什么是Sed

 

        Sed即StreamEDitor中3个大写字母的组合,是一种“流编辑器”。所谓流编辑器,就是面向流的编辑器。所谓流就是应用程序的输入经过程序处理,然后输出到标准输出。通俗点说,sed就是一种通过输入流,比如文件、键盘的输入,然后处理,最终输出到标准输出(即屏幕)的一种文本编辑器。它是unix-like系统下的一个常用文本处理命令。

 

0.2 Sed相关的正则表达式

 

       读者请注意,通常我们把grep和sed视为一组,因为它们都使用shell的基础正则表达式,我们把egrep和awk视为一组,它们可以使用扩展的正则表达式。这里我们只介绍sed相关的正则表达式,即shell基础正则表达式语法。先说明,不要担心学不会,因为非常简单!

 

.        代表除去换行符以外的任意单个字符

 

例1:c.t 可以代表cat,cut,c!t等等

 

*       不同于通配符,代表重复*前边一个字符任意次,即0次或多次

 

例2:hello_*world!代表helloworld!,或者hello_world!,或者hello__world!等等

 

[…]   代表它内部包括的字符的任意一个

 

例3:a[1234]c代表a1c,或者a2c,或a3c,或a4c

 

^       放在正则表达式的开始处,代表一行的开始位置,放在[]中的开始处,代表不是[]中字符的任意字符

 

例4:^a[^1234]c代表文本中某一行以axc三个字符开头,其中x为不是1234的任意字符

 

$       放在正则表达式的结尾处,代表一行的结束

 

例5:abc$ 代表文本中以abc结尾的文本行

 

\{n,m\}    代表重复前边一个字符n到m次中的任何一种。变种有\{n\}重复前边一个字符n次,\{n,\}重复前边一个字符至少n次。

 

例5:abc\{2,3\}代表abcc或者abccc

 

\<     代表一个单词的开始

 

例6:\<Hello代表包含以Hello开头的单词的行

 

\>     代表一个单词的结束

 

例7:Hello\>代表包含以Hello结尾的单词的行

 

&      代表匹配内容

 

例8:s/hello/[&]/g,会将文本中的hello都替换为[hello],其中&代表匹配的hello

 

\n     n是1-512的任意数字,代表前边第n个符合\(…\)的匹配

 

例9:s/\([1-9]*\)abc\([A-Z]*\)/\2\1/g表达式,会将123abcABC转换为ABC123,其中\1代表\([1-9*]\], \2代表\([A-Z]*\)

 

PartI    Sed基本原则

1.1 Sed命令的作用规则

 

1.      脚本文件中的所有命令会顺序作用于待处理文本中的每一行;

 

2.      地址过滤作用可以使脚本中的命令只作用于与地址匹配的特定行;

 

3.      原始文本文件不会被改变,被改变的是原始文件的一个备份,处理后的备份行会输出。

 

1.2 模式空间(The Pattern Space or The Temporary Buffer)

 

       存放sed脚本命令处理的当前行,即当前处理行的备份,命令实际改变的是这份备份,最后输出的也是这份备份。

 

1.3 Sed命令地址详解

 

(四种地址情况) 其中,地址可以是“正则表达式、行号、行中部分文本信息”三种

 

1.  无地址 脚本中命令作用于所有行,例如 d 删除所有行

 

2.  一个地址 命令作用于与地址匹配的对应行,例如 1d删除第一行,2d删除第二行

 

3.  逗号分隔的两个地址 命令作用于两个地址之间的所有行,例如1,/^$/d删除第一行到第一个空行之间的所有行

 

4.  地址后直接跟!号,命令作用于所有与地址不匹配的行 例如1!d删除除第一行外的所有行

 

1.4 大括号的使用

 

作用:嵌套地址,组合命令。左大括号必须在一行的末尾,右大括号必须独立成行,大括号后边直接跟回车,不能有空格

 

例1:删除1-5行中的空白行

 

1,5{

 

         /^$/d

 

}

 

例2:从1-5行中删除含linux或unix的行

 

1,5{

 

         /linux/d

 

         /unix/d

 

}

 

1.5 Sed应用场景

 

1 同时编辑多个同类文件

 

2 修改文件内容

 

3 提取文件内容

 

1.6 Sed命令的两种使用方式

 

方式一:使用脚本文件,语法:sed [other options] –f script.sed file

 

方式二:直接使用命令行,语法 sed [options] ‘command’ file

 

Sed命令使用时,可以直接在命令行使用,将命令通过单引号括起来,也可以将命令按行写在一个文本文件中,然后使用Sed的-f选项来加载脚本文件中的Sed命令集合。

 

1.6.1 命令行方式

 

         最简答的命令行方式,比如sed‘1d’ file,表示删除文本文件file中的第一行;

 

         复杂点的就是包含多个命令的情况,有三种解决方式:第一种,在一个单引号里使用分号分隔各个命令,比如sed ‘1d;5d;9d’ file,就是删除第1,5,9行文本;第二种,使用多个-e选项分隔各个命令,比如sed –e ‘1d’ –e ‘5d’ –e ‘9d’ file;第三种,使用换行符来分隔各个命令,比如,其中#代表shell的命令提示符,>代表键入回车后的提示符:

 

# sed ‘1d  <键入回车>

 

> 2d  <键入回车>

 

> 3d’ file

 

更为复杂点的是,命令中含有用于过滤文本行的地址信息,同时要求执行多个命令,这时候要使用大括号{}。比如

 

# sed ‘5,/^$/{   <键入回车>

 

> /hello/d   <键入回车>

 

>s/word/words/g   <键入回车>

 

> }’ file

 

其中,5,/^$/ 代表仅针对第5行到后边第一个空白行间的文本行,/hello/代表含有hello的文本行,s命令代表将word全部替换为words,g标记代表处理对应行中所有出现的word,没有g代表仅处理对应行中第一个word。

 

注意:有些情况使用大括号可以不用键入回车,但是键入回车肯定可以保证不出问题,所以建议始终在使用大括号时键入回车!

 

1.6.2 脚本文件方式

 

         了解了上边的命令行方式,就好了解脚本方式了。脚本方式就是将多条命令放置到一个文本文件中,其格式如下:

 

/address/{

 

Cmd1;

 

Cmd2;

 

 

Cmdn;

 

}

 

         这种形式其实和sed命令行使用大括号是一样的,只是由于命令多了,写在文件了比较方便,而且便于重用。其中,内部的cmd可以是以上形式的嵌套,就是大括号里面还可以再有地址,然后在使用大括号,到括号里面又是命令。

 

将以上内容存于文件中,然后使用以下命令,即可执行:

 

sed –f script.file file

 

PartII 初级Sed命令

2.1 基本Sed命令语法

 

Sed命令语法:[address]command

 

Sed语法:sed [options] [actions]file

 

1.      Sed –f sed.script file

 

2.      Sed ‘actions’ file

 

3.      Sed在命令行使用多条命令的三种方式:

 

使用多个-e选项,每个后边接一条命令;

 

使用分号分隔多条命令;

 

在写闭合的单引号之前使用回车,每条命令后边加回车

 

Sed使用#作为注释符号,#号后边紧跟n,相当于使用-n参数,不默认输出文本内容

 

2.2 Sed主要选项

 

-n      抑制命令自动输出patternspace中的内容,默认情况下,pattern space中的内容,如果执行完所有处理命令,结果会被输出,使用该选项使得patternspace中的内容不会自动输出,通常该选项和p命令一起使用,以便输出当前处理行,单独使用p命令,同一行会被输出两次。

 

-f       用于使用sed脚本的情况,后接脚本文件名

 

-e      后接单引号括起来的命令串,使用多个命令,可以通过多次使用-e选项实现

 

-i       直接修改原文件内容,默认不输出到屏幕

 

-r      在命令中使用扩展的正则表达式,扩展正则表达式,我们会在<<掌握awk命令>>中提到,强大的选项!!!(该选项不在本文讨论范文内)

 

2.3 12种基本命令

 

Subsititution:即s命令,文本替换命令(常用

 

语法:[address]s/pattern/replacement/flag

 

Address代表要处理的行,可以是行号,正则表达式,特定行中的部分文本片段

 

Pattern代表模式字符串

 

Replacement代表用来替换模式字符串的字符串

 

Flag有n,g,p,w file四种,n代表(1-512)中一个数字,表示替换操作作用于当前行中出现的第几个pattern串;g代表替换操作处理当前行中出现的所有pattern串,p代表打印当前行,该标志通常与-n选项连用,表示只打印处理过的行;w file表示将处理行写入文件file中。

 

注意:分隔用的/可以使用其他合法符号,比如!,:等,最后,不使用任何标志表示仅作用于第一个匹配

 

Replacement中可用的三种特殊符号:& 代表pattern匹配的字符串,\n代表由第几个\(pattern\)匹配的串,\代表转义字符,在Replacement中只有这三个特殊符号,其他都不是特殊符号,不需要转义

 

Delete,即命令d,删除命令,语法:[address]d(常用

 

删除匹配形式的行,注意是删除整行,而不是仅删除行中匹配的模式字符串

 

Append,Insert,Change,即命令a,i,c,追加、插入、更改命令,语法[address](a|i|c) \replacement

 

Append在指定行后插入,insert在指定行前插入,change用replacement替换指定行

 

List命令,即l命令,列出指定行中的不可打印字符,如tab键,换行符等

 

Transform命令,即命令y,转换命令,最特殊的一个命令,所有其他命令都是对应单词的首字母,只有这个命令不是对应单词首字母,因为test(t)命令已经存在了。

 

语法:y/abc/ABC/ 该命令用于对应字符转换,类似于tr,但没有tr命令应用范围广,abc与ABC必须字符个数相等,对应转换,而不能使用[0-9]这种形式,即a转换为A,b转换为B,c转换为C。

 

Print命令,即p命令,打印匹配行,通常与选项-n一起使用,不使用-n同一行会被打印两次。特殊符号=,与p命令联合使用,可以输出行号,行号独立成行,=等号必须是地址后边第一个出现,在p命令之前(常用

 

例子:输出第一行到第一个空行中的所有行,并输出行号

 

1,/^$/{

 

=

 

p

 

}

 

Next命令,即n命令。输出当前行,并将下一行输入到模式空间中。(常用

 

注意:出现在n命令之前的命令不会作用于新输入的行,出现在n命令之后的命令也不会作用于n命令输出去的行

 

ReadWrite命令,即r和w命令,如法[address](r|w)file

 

r,将文件读入到当前行之后

 

w,将当前行写入到文件

 

Quit命令,即q命令,遇到地址行就退出sed,其中匹配的地址行也要输出

 

 

其中,s,d,p,n是最常用的几个命令,y是最特殊的一个命令,因为其它所有命令都是以单词首字母命名,它不是。

 


 

PartIII    高级Sed命令

3.1多行模式空间与备份空间

 

 

多行模式空间(MultilinePattern Space):就是在模式空间中放置输入文件的多个行内容。

 

 

备份空间(The Hold Space):用于备份Pattern Space中的内容的空间。

 

 

3.210种高级Sed命令

 

 

三组高级sed命令:

 

 

1操作多行模式空间的命令(N,D,P)

 

 

2处理模式空间与备份空间内容交换的命令(H,h,G,g,x)

 

 

3 sed脚本控制流命令(b,t)

 

 

N,D,P命令分别为n,d,p命令的大写形式,其含义类似,略有不同:

 

N命令,与n不同,它不输出模式空间中的当前行,而是将下一行也输入到模式空间中,当前行与下一行之间插入一个’\n’,以下为示意图:

 

                                                                    图1. 调用N命令后的Multiline Space

注意:调用N后只有最初和最后有^$标记,\n前后并没有这些标记

D命令不同于d命令,d命令删除Pattern Space中的内容,而D命令仅删除Multiline Space中第一个’\n’之前的内容,如图1 中,即删除“The Unix Operating System”,而“Is A interesting System”仍然存在。同时,它使得脚本的控制流转到脚本文件的第一行,跳过该命令的后续命令。

P命令不同于p命令,p命令打印Pattern Space中的内容,而P命令仅打印Multiline Space中第一个’\n’之前的内容,如图1中,即仅打印“The Unix Operating System”.

 

Hh命令,hold之意,将Pattern Space中的内容备份到Hold Space中,大写命令是追加到Hold Space中,小写命令是覆盖HoldSpace中的内容;

Gg命令,get之意,即将Hold Space中的内容取到Pattern Space中,大写代表追加,小写代表覆盖。

x命令,交换Pattern Space和Hold Space中的内容。

 

b命令(branch)和t命令(test)用于控制sed脚本流程。

b命令语法:[address]b[label]

例子:

:Hello

         Command

         Command

         /address/b Hello

         Command

b命令使得脚本控制流转到:Hello的下一行,如果没有使用标签,则直接跳转到脚本结尾。

t命令语法:[address]t [label]

例子:

s/\n//

t

command

t命令含义是,如果上边的替换命令s成功,则跳转到标签处,如果没有标签,跳转到脚本结尾,如果不成功则继续执行后续命令。

总结,掌握Sed,掌握Shell的基本正则表达式,12中基本Sed命令+10中高级Sed命令,Sed命令除y命令(transform)外,其它命令都是英文单词首字母,很好记忆。当然,这里不是Sed的全部命令,其它一些命令不太常用,就不再介绍。最后一部分,我们以一些常见的sed命令处理案例,来加深理解上边的理论介绍部分,以便彻底掌握这个实用工具。

 

PartIV 实践练习

 

[d删除命令]

 

$ sed 2d file          #删除file中的第2行

 

$ sed 2,$d file            #删除第2行到最后一行的所有行

 

$ sed /hello/ file      #删除包含hello的行

 

$ sed 1d;5d;10d file    #删除第1,5,10行

 

$ sed /^$/d file        #删除file中的空行

 

$ sed 5,10!d file       #删除5-10以外的所有行

 

总结:d命令有三种地址模式,行号,行中字符串片段,正则表达式,对于后两种需要使用//包围地址,如/hello/和/^$/,还有一点,两个地址间的逗号,表示作用范围为两个地址之间,!代表取补集

 

 

 

[s 替换命令]

 

$ sed s/test/Test/ file              #用Test替换每行中第一个test

 

$ sed s/test/Test/5 file              #用Test替换每行中第5个出现的test

 

$ sed s/test/Test/g file              #用Test替换每行中所有test

 

$ sed ns/^test/Test/p file          #-n与p合用,仅显示发生替换操作的行,

 

#Test替换以test开头的行的开头的test

 

$ sed s/^192.168.0.1/&localhost file  # &表示匹配到的内容,用

 

#192.168.0.1localhost替换以192.168.0.1

 

#开头的行的开头的192.168.0.1

 

$ sed ns/\(love\)able/\1rs/p file   #\1代表\(love\)匹配到的内容,用lovers

 

#替换包含love的行中第一个出现的love

 

$ sed s#10#100#g file                 #用100代替每行出现的10,这里#等于/

 

$ sed n/test/,/check/p file         #仅打印第一包含test的行到第一个包含

 

#check的行之间的所有行

 

$ sed n5,/^test/p file              #打印第5行到第一个以test开头的行

 

#之间的所有行

 

$ sed /test/,/check/s/$/HelloEnd      #在第一个包含到第一个包含check的行

 

#后边追加HelloEnd

 

$ sed e1,5des/test/check/ file  #删除1-5行的内容,将文件中每行第一个

 

#test替换为check,前边命令影响后边命令

 

总结:命令中体现了p命令的使用,通常与-n选项连用,s命令是最常用的,注意分隔符可以用其他符号代替,注意逗号可以表示地址区间,以及//包围地址的使用

 

 

 

[n下一行命令]

 

$ sed /test/{n;s/aa/bb/} file       #读到含test的行,输出该行,然后

 

#读入下一行,用bb替换下一行出现

 

#的第一个aa,循环执行以上动作

 

该命令可以写为以下方式

 

$ sed /test/{  <键入换行符>

 

>n  <键入换行符>

 

>s/aa/bb <键入换行符>

 

>} file

 

总结:n命令前边的命令不会作用于下一行,n命令后边的命令不会作用于当前行

 

[r 文件读入命令]

 

$ sed /test/rfile2 file1    #将file2的内容插入到file1中含有test的每一行之后

 

[w 文件写入命令]

 

$ sed /test/wfile2 file1   #将file1中每个含有文本test的行追加到file2中

 

[a 追加命令]

 

$ sed /test/a\thisis append line file #在含有文本test的行后边插入一行内容为

 

                                        #thisis append line的文本

 

[i 插入命令]

 

$ sed /test/i\thisis a insert line file #类似如a命令,在对应行前边插入

 

[c 替换命令]

 

$ sed 3,5c\thisis a change linefile    #将文件file的第3-5行内容替换为一行,

 

                                          #其内容为this is a change line

 

[y 转换命令]

 

$ sed 1,10y/abcd/ABCD/ file      #将file前10行中所有的字符a,b,c,d转换为大写

 

[q 退出命令]

 

$ sed 10q file                   #处理完(默认为打印)第10行,sed命令结束

 

                                  #q命令与b,t等命令可以用于流程控制

 

[N 下一行追加命令]

 

问题描述:用sed实现去换行的功能,即tr d\n的功能

 

sed fscript.file file   #其中script.file为sed脚本文件,名字可以随便取

 

                          #file为待处理文件

 

Script.file脚本文件内容如下:

 

 

 

{

 

N             #将下一行追加到模式空间,现在空间中有两行内容,中间用\n分隔

 

s/\n//        #删除\n,执行完这里sed对下一行继续处理

 

}

 

当然,左大括号{左边可以通过加地址信息限制处理哪几行,这个功能当然可以不写脚本文件,直接在命令行执行,如下:

 

sed N;s/\n// file

 

再强调一次,脚本文件都可以写成命令行方式,放过来也成立,就是看你觉得怎么方便而已!

 

 

 

[N P D 循环] #联合使用N-P-D,操作控制流

 

问题描述:如下文本文件,如果UNIX System出现以下情况:UNIX是一行的最后一个单词,System是下一行的第一个单词,则将UNIX System替换为UNIX Operating System,新的换行符在System之后。

 

file内容如下:

 

Here are examples of the UNIX

 

System. Where UNIX

 

System appears, it should be the UNIX

 

Operating System.

 

处理后输出结果为:

 

Here are examples of the UNIX Operating System.

 

Where UNIX Operating System appears, it should be theUNIX

 

Operating System.

 

 

 

实现脚本如下:

 

/UNIX$/{

 

    N   #在UNIX结尾的行后追加下一行,中间有\n分隔

 

    s/\n\(System.*\)/ Operating \1\n/  #替换,这里的特殊用法稍后讲述

 

    P   #输出\n之前的内容

 

D   #删除\n之前的内容,并跳转至脚本第一行,即/UNIX$/{处

 

}

 

 

 

备注:N是在模式空间追加一行,两行之间有一个分隔符\n;P是打印多行模式空间中第一个\n之前的内容,也就是第一行;D是删除第一个\n之前的内容,并使得控制流程跳转至脚本第一行,如果D后边还有命令,执行D后,后边的命令式执行不到的。

 

 

 

如果将脚本中替换命令那行换为以下一句,输出结果略有不同:

 

s/\nSystem/ Operating System\n/

 

输出结果为:

 

Here are examples of the UNIX Operating System

 

.Where UNIX Operating System

 

 appears, itshould be the UNIX

 

Operating System.

 

 

 

这里面有一些标点的问题,因此,我们做了特别处理,说明如下:

 

\(System. *\)代表System后边有一个任意字符,这是为了处理空格和句号的,后边*前边有个空格,这里看不出来,实际是输入了一个空格,这个代表,之后出现0个或多个空格,而其中用反斜杠和小括号括起来,代表后边\1指的就是这个匹配。如果这里有不明白的,可以翻看前边关于\(\)和\1的介绍。

 

[h,H,g,G,x模式空间与备份空间命令]

 

这几个命令就是在两个空间中互相操作,比较好理解,这里不再举例。

 

[b,t]流程跳转命令,根据前边的理论介绍也比较好理解,不再举例。


 

posted @ 2013-10-31 21:30  pangbangb  阅读(320)  评论(0编辑  收藏  举报