云中烛火

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

概述

 1.sed是一款流编辑工具,用来对文本进行过滤与替换工作

   sed通过输入读取文件内容,但一次仅读取一行内容进行某些指令处理后输出,所以sed更适合于处理大数据文件。

 2.sed流程:

   通过文件或管道读取文件内容。

  sed并不直接修改源文件,而是将读入的内容复制到缓冲区中,我们称之为模式空间(pattern space)。

   根据sed的指令对模式空间中的内容进行处理并输出结果,默认输出至标准输出即屏幕上。

 

sed基本语法格式

   sed Options... [script] [inputfile...]

   sed 选项... [脚本指令] [输入文件] 如

 如果没有输入文件,则sed默认对标准输入进行处理(即键盘输入)。脚本指令是第一个不以“-”开始的参数。

 1.选项含义:

    --version  显示sed版本。

   --help   显示帮助文档。

   -n,--quiet,--silent   静默输出,默认情况下,sed程序在所有的脚本指令执行完毕后,将自动打印 模式空间中的内容,这些选项可以屏蔽自动打印。

   -e script   允许多个脚本指令被执行。

   -f script-file, --file=script-file   从文件中读取脚本指令.

   -i,--in-place   直接修改源文件,经过脚本指令处理后的内容将被输出至源文件(源文件被修改)

   -l N, --line-length=N   该选项指定l指令可以输出的行长度,l指令用于输出非打印字符。

   --posix   禁用GNU sed扩展功能。

   -r, --regexp-extended   在脚本指令中使用扩展正则表达式

   -s, --separate   默认情况下,sed将把命令行指定的多个文件名作为一个长的连续的输入流。而GNU sed则允许把他们当作单独的文件, 这样如正则表达式则不进行跨文件匹配。

    -u, --unbuffered 最低限度的缓存输入与输出。

 

2.简单案例:

  就简单介绍几个脚本指令操作作为sed程序的例子。

  a,append 追加

  i,insert 插入

  d,delete 删除

  s,substitution 替换

[root@localhost ~] #cat test.txt
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.1.1
NETMASK=255.255.255.0
GATWAY=192.168.0.254

 

 

[root@localhost ~] #sed '2a TYPE=Ethernet' test.txt

第二行后添加TYPE=Ethernet

 

[root@localhost ~] #sed '3i TYPE=Ethernet' test.txt

第三行前添加TYPE=Ethernet

 

 

[root@localhost ~] #sed 's/yes/no/g' test.txt

将样本文件中的所有yes替换为no

 

 

[root@localhost ~] #sed '3,4d' test.txt

删除第3至4行的内容

 

 

以上大多数操作指令,都依据行号定位操作对象(地址),如:2a即第二行后添加。 但实际情况可能大多数情况你并不确定你要操作对象(地址)的行号,这时更多的我们会使用正则表达式确定操作对象(地址)。

下面是使用正则表达式定位操作行的示例:

 

 

[root@localhost ~] #sed '/ONBOOT/a TYPE=Ethernet' test.txt

匹配到包含ONBOOT的行,并在其后添加TYPE=Ethernet

 

 

[root@localhost ~] #sed '/^GATEWAY/d' test.txt

匹配以GATEWAY开始的行,并删除该行

 

 

 另外我们的操作指令可以,写入到脚本文件中并通过sed的-f选项读取。 创建一个sed脚本,内容如下:

 

[root@localhost ~] #cat sed.sh
/^$/d

这条指令的作用是:匹配到空白行后,删除该行。

 

 

[root@localhost ~] #sed -f sed.sh test.txt

对test.txt文件执行sed.sh指令

 

 

 对test.txt文件执行sed.sh指令 另外,当你需要执行多个指令时,可以使用以下三种方法:

 1.使用分号隔开指令。

[root@localhost ~] #sed 's/yes/no/;s/static/dhcp/' test.txt

2.使用-e选项。

[root@localhost ~] #sed -e 's/yes/no/' -e 's/static/dhcp/' test.txt

3.利用分行指令

[jacob@localhost ~] #sed ' 
>s/yes/no/ 
>s/static/dhcp/' test.txt

 

然而在命令行上输入过长的指令是愚蠢的,这时就需要-f选项指定sed脚本文件,在脚本文件中可以包含多行指令,而且便于修改!

 

简单正则表达式

正则表达式速查表

 1.为sed指令确定操作地址:

   number   指定输入文件的唯一行号。

   first~step   以first开始,并指定操作步长为step,如1~2,指定第一行,第三行,第五行... 为操作地址。

   /regexp/   //中间包含的是正则表达式,通过正则表达式匹配操作地址。

     注://空的正则表达式,匹配最近一次正则表达式的匹配地址,会在后面使用看出效果。

   \cregexpc   匹配扩展正则表达式,c字符可以使用任意字符替代。

   addr1,addr2   匹配从操作地址1到操作地址2的所有行。

   addr1,+N   匹配地址1以及后面的N行内容。

 

2.正则表达式概述(对你要找内容的一种描述)

  char      字符本身就匹配字符本身,如/abc/就是定位包含abc的行

  *      匹配前面表达式出现了0或若干次,如/a*/可以帮你找到a,aa,aaa,... ...等等。

   \+     类似于*,但匹配前面表达式的1次或多次,这属于扩展正则表达式。

  \?      类似于*,但匹配前面表达式的0次或1次,这属于扩展正则表达式。

  \{i\}    类似于*,但匹配前面表达式的i次(i为整数),如:a\{3\}可以帮你找到aaa。

  \{i,j\}   匹配前面表达式的i到j次,如a\{1,2\}可以帮你找到a或aa或aaa。

  \{i,\}    匹配前面表达式至少i次。

  \( \)    将\( \)内的模式存储在保留空间。最多可以存储9个独立子模式,可 通过转义\1至\9重复保留空间的内容至此点。

  \n     转义\1至\9重复保留空间的内容至此点。

例:test.txt的内容为ssttss
grep '\(ss\)tt\1' test.txt     \1表示将ss重复在tt后面 该grep命令等同于grep ssttss test.txt 在test.txt文件中找ssttss

  .      (点)匹配任意字符。

  ^     匹配行的开始,如^test 将匹配所有以test开始的行。

  $     匹配行的结尾,如test$ 将匹配所有以test结尾的行。

  []    匹配括号中的任意单个字符,如a[nt] 将匹配an或at。

  [^]    匹配不包含在[]中的字符,如[^a-z] 将匹配除a-z以外的字符。

  \n    匹配换行符。

  \char   转义特殊字符,如\*,就是匹配字面意义上的星号。

 

sed脚本指令(注释、替换、删除、追加、打印、下一行、读写文件、退出、多行模式)

常用的sed脚本指令有:

  *注释(#)

  *替换(s)

  *删除(d)

  *追加(a)

  *插入(i)

  *更改(c)

  *列印(l)

  *转换(y)

  *打印(p)

  *读写文件(r,w)

  *退出(q)

  *下一步(n) *Next(N)
  *Print(P)

  *Delete(D)

  *Hold(h,H)

  *Get(g,G)

  *branch,test

 sed脚本指令的基本格式:

   [address]command

  [地址]命令       备注:有些命令仅可以对一行操作,有些可以对多行操作。

 

   命令可以用大括号进行组合以使命令序列可以作用于同一个地址:

   address{

     command1

     command2

     command3

  }

   第一个命令可以和左大括号在同一行,但右大括号必须单独处于一行。

  注意事项:命令后添加空格会产生错误。

 1.注释(#):

    注释行是以#开始的行,如果#后面的字符为n,则屏蔽sed程序的自动输出功能,等同于命令选项-n。

 2.替换(s,Substitution):

   [address]s/pattern/replacement/flags   

      address为操作地址,s为替换指令,/pattern/匹配要替换的内容,/replacement/为替换的内容。

        flags可以是: n   1至512之间的数字,表示对模式空中指定模式的第n次出现进行替换。 如一行中有3个A,而只想替换第二个A。 g 对模式空间的匹配进行全局更改。没有g则仅第一次匹配被替换,如一行中有3个A,则仅替换第一个A。 p 打印模式空间的内容。 w file 将模式空间的内容写到文件file中。

      replacement为字符串,用来替换与正则表达式匹配的内容。 在replacement部分,只有下列字符有特殊含义:

         & 用正则表达式匹配的内容进行替换。 \n 匹配第n个子串,这个子串之前在pattern中用\( \)指定。 \ 转义(转义替换部分包含的:&, \等)。

 

示例:

 示例1:

  test.txt

<html>
     <title>First Web</title>
     <body>Hello the World! <body>
</html>

 

----将样本文件中的第二个<body>替换为</body>

sed.sh

/body/{
     s//\/body/2         注:替换与行匹配相同的内容即body,替换为/body,但仅替换第二个body为/body。
 }    

 

[root@localhost ~] #sed -f sed.sh test.txt

 

<html>
     <title>First Web</title>
     <body>Hello the World!</body>
</html>

 

 

  示例2:

test.txt

<html> 
    <title>First Web</title> 
    <body> 
            h1Helloh1
            h2Helloh2
            h3Helloh3
     </body>
 </html>                    

 

----给所有第一个的h1,h2等添加<>;第二个h1,h2添加</>

sed.sh

/h[0-9]/{  注:匹配h紧跟一个数字的行 
     s//\<&\>/1     注:替换与上一行中匹配内容相同的内容,即替换h[0-9],替换为<&>,其中&即前面要替换的内容。
     s//\<\/&\>/2   注:上一条指令仅替换第一个h1,h2...,本行指令用来替换第
二个h1,h2...。 
}

 

[root@localhost ~] #sed -f sed.sh test.txt
<h1>Hello</h1> 
<h2>Hello</h2> 
<h3>Hello</h3>

 

技巧:关于 's///' 命令的另一个妙处是 '/' 分隔符有许多替换选项。

如果规则表达式或替换字符串中有许多斜杠,则可以通过在 's' 之后指定一个不同的字符来更改分隔符。

示例:$ sed -e 's:/usr/local:/usr:g' mylist.txt   这里:为分隔符。

 

3.删除(d ,delete):

删除指令删除匹配的行,而且删除命令还会改变sed脚本中命令的执行顺序。因为: 匹配的行一旦被删除,模式空间将变为“空”,自然不会再执行sed脚本后续的命令。

删除命令将导致读取新的输入行(下一行),而sed脚本中的命令则从头开始执行。

注意事项:删除将删除整个行,而不只是删除匹配的内容。(如要删除匹配的内容,可以使用替换)

 

示例1.删除文件中的空白行

test.txt

DEVICE=eth0 
ONBOOT=yes 
BOOTPROTO=static 


IPADDR=192.168.0.1 
NETMASK=255.255.255.0 



GATEWAY=192.168.0.254

 

sed.sh

/.*/{
        /^$/d
}

 

[root@localhost ~] #sed -f sed.sh test.txt

 

4.追加(a):在匹配行后追加内容

test.txt

DEVICE=eth0
ONBOOT=yes 
BOOTPROTO=static 
NETMASK=255.255.255.0 
GATEWAY=192.168.0.254
[root@localhost ~] #sed '/static/a IPADDR=192.168.0.1' test.txt

 

5.插入(i):在匹配行前插入内容

[root@localhost ~] #sed '/NETMASK/i IPADDR=192.168.0.1' test.txt   

注:在NETMASK行前添加一行。

 

6.更改(c):更改匹配行的内容

[root@localhost ~] #sed '/ONBOOT/c ONBOOT=yes' test.txt

注:包含ONBOOT的行(整行)替换为ONBOOT=yes。 7.

 

7.列印(l):显示模式空间中的内容,显示非打印字符,一般与-n一起使用,否则会输出两次。

[root@localhost ~] # sed -n '1,2l' test.txt

结果如下:

  DEVICE=eth0$

  ONBOOT=yes$

8.转换(y):按字符的转换

[address]y/source-chars/dest-chars/

 

test.txt

DEVICE=eth0 
ONBOOT=yes 
BOOTPROTO=static 
netmask=255.255.255.0 
GATEWAY=192.168.0.254

sed.sh

/.*/{
        /netmask/y/abcdefghijklmnopqrstuvwxyz/ABCEDFGHIJKLMNOPQRESUVWXYZ/    #将小写转换为大写
}

 

[root@localhost ~] #sed -f sed.sh test.txt

 

 

9.打印(p):作用类似与l(列印),但不显示非显示字符,一般与-n配合使用,脚本文件中需要#n

[root@localhost ~] #sed -n '1,2p' test.txt

 

10.读写文件(r,w):[line-address]r file, [address]w file

name.txt

Jacob 
Tom 
Jerry

mail.txt

jacob@gmail.com 
tom@gmail.com 
jerry@gmail.com

sed.sh

/.*/{
     $r mail.txt 
}

 

[root@localhost ~] #sed -f sed.sh name.txt

结果:

Jacob 
Tom 
Jerry 
jacob@gmail.com 
tom@gmail.com 
jerry@gmail.com

 

 11.退出(q): 匹配地址后退出sed脚本

 

[root@localhost ~] #sed '10q' test.txt     #打印文件前10行内容(到第10行后退出sed脚本指令)。

 

 12.下一步(n): [address]n

输出模式空间中的内容,然后读取输入的下一行。 next命令改变了正常的sed脚本指令的流程,默认只有到sed脚本的底部才会输出模式空间的内容。 next命令导致输入的下一行取代模式空间中的当前行,sed脚本中的后续命令将应用于替换后的行,而不是当前行。

 name.txt

Jacob 
Tom 
Jerry

sed.sh

/.*/{
        n        读取下一行后删除(删除偶数行)。
        /.*/d
}
[root@localhost ~] #sed -f sed.sh name.txt

结果:

Jacob 
Jerry

 

13.Next(N):

多行Next(N)命令通过读取新的输入行,并将它添加到模式空间的现有内容之后,来创建多行模式空间。 模式空间的最初内容与新的输入行之间用换行符分隔。在模式空间中插入的换行符可以使用\n匹配。

示例1

test.txt

111 
222 
222 
333

sed.sh

#n
/222/{
        N
        l
}
[root@localhost ~] #sed -f sed.sh test.txt

结果:

222\n222

示例2

test.txt

111 
222 
222 
222 
333

sed.sh

#n 
/222/{ 
    N 
    l 
}
[root@localhost ~] #sed -f sed.sh test.txt

结果:

222\n222 
222\n333

 

14.Print(P):多行打印(P)与打印(p)稍有不同,该命令仅输出多行模式空间中的第一部分,直到第一个插入的\n换行符为止。

 

15.Delete(D): 

删除命令(d)删除模式空间中的内容并导致读入新的输入行,而sed脚本重新执行。 删除命令(D)删除模式空间中直到第一个插入的换行符(\n)前的这部分内容,它不会读入新的输入行,并返回sed脚本的顶端,使得剩余指令继续应用于模式空间中剩余的内容。

 

posted on 2015-06-03 10:35  云中烛火  阅读(146)  评论(0)    收藏  举报