Sed基本入门[1] 基础知识

1、What's sed?


如果你是一个开发、系统管理员或者数据库管理员又或者是it管理员,或者只是一个经常在unix/linux环境下工作的人,你应该掌握sed和awk。
Sed→Stream Editor,它是一个非常强大的工具,可以用来操作、过滤和转换文本。Sed可以从文件中获取输入,也可以从管道中获取输入。

2、Basic Syntax


sed [options] {sed-commonds} {input-file}

 sed一次从input-file中读取一行文本,然后在这一行文本上执行sed-commonds,接着读取下一行文本,再执行sed-commonds,重复执行这个过程,直到读取input-file的最后一行之后。

sed-commonds可以是一个命令也可以是一组命令。如果是一个命令,可以如以下的方式执行:

sed -n 'p' /etc/passwd

在上面的示例中,-n为选项 p为命令,/etc/passwd为输入文件。

如果需要执行的是一组命令,需要在每个命令前加上选项-e,表示是需要执行的命令,其基本语法为:

sed [options] -e {sed-command-1} -e {sed-command-2} {input-file} 

示例:

$ sed -n -e '/^root/ p' -e '/^nobody/ p' /etc/passwd 

如果通过几个-e参数执行多个命令,可以把他们通过反斜杠分成多行,例如:

$ sed -n \
-e '/^root/ p' \
-e '/^nobody/ p' \
/etc/passwd 

你也可以把通过花括号把要执行的多个sed命令写到一组,其基本语法为:

sed [options] '{
sed-command-1
sed-command-2
}' input-file

示例:

$ sed -n '{
/^root/ p
/^nobody/ p
}' /etc/passwd

我们还可以把要执行的sed命令写到一个文件中,然后通过-f选项来使用该文件,其基本语法为:

sed [options] -f {sed-commands-in-a-file} {input-file}

示例:

$ vi test-script.sed
/^root/ p
/^nobody/ p
$ sed -n -f test-script.sed /etc/passwd 

 

3、Sed Scripting Flow


PEPR:

  • Read:把一行文本读取到模式空间(Pattern Space,一个内部的临时buffer)。
  • Execute:在模式空间内保存的文本上执行sed命令。如果有多个sed命令,则会依次执行。
  • Print:打印输出模式空间中的文本,打印后,模式空间为空。
  • Repeat:重复执行上述操作,直到文件的末尾。

具体流程可以参考下图:

 4、p command and Address Range


在接下来的示例中,我们会多次以文本文件employee.txt作为sed操作的对象进行示范:

$ vi employee.txt 
101,John Doe,CEO 
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Manager

 

使用p命令,可以打印当前模式空间中的内容。

为什么需要p命令?
3 Sed Scripting Flow 中提到了Print,也就是说sed自动也会打印模式空间中的内容,那为什么还需要有一个专门的打印命令p呢?因为使用p命令,你可以更加详细的指定打印哪些内容或者说不打印哪些内容。通常情况下,使用p命令时,配合使用-n选项来抑制标准sed流程中的默认打印,否则文本可能会打印两行:

$ sed 'p' employee.txt 
101,John Doe,CEO
101,John Doe,CEO
102,Jason Smith,IT Manager
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
104,Anand Ram,Developer
105,Jane Miller,Sales Manager
105,Jane Miller,Sales Manager

使用-n选项后:

$ sed -n 'p' employee.txt 
101,John Doe,CEO
102,Jason Smith,IT Manager
103,Raj Reddy,Sysadmin
104,Anand Ram,Developer
105,Jane Miller,Sales Manager 

Address Range:

通过在sed命令前指定地址范围,可以只在特定的行上执行sed命令,否则默认在所有的行上执行。例如以下代码片段只在第二行上执行打印命令:

$ sed -n '2 p' employee.txt 
102,Jason Smith,IT Manager 

而以下代码片段只在2到最后一行行上执行打印命令:

$ sed -n '2,$ p' employee.txt 
102,Jason Smith,IT Manager 
103,Raj Reddy,Sysadmin 
104,Anand Ram,Developer
105,Jane Miller,Sales Manager

常见的地址范围用法:

  • n:匹配第n行
  • n,m:匹配第n到m行
  • n,+m:匹配从第n行及接下来的m行
  • n~m:匹配从第n行开始的每m行记录,例如:1~2匹配1,3,5,7,...;2~2匹配2,4,6,8,...;2~3匹配2,5,8,....

模式匹配(Pattern Matching)

正如可以使用地址范围一样,也可以使用一个模式匹配,例如以下几个示例:

打印匹配模式"Jane"的行:

 sed -n '/Jane/ p' employee.txt 
105,Jane Miller,Sales Manager 

打印从匹配模式"Raj"开始的行到匹配模式"Jane"的行:

$ sed -n '/Raj/,/Jane/ p' employee.txt 
103,Raj Reddy,Sysadmin 
104,Anand Ram,Developer 
105,Jane Miller,Sales Manager

 甚至可以结合模式匹配和地址范围,例如打印从匹配模式"Jason"及后面的两行:

$ sed -n '/Jason/,+2 p' employee.txt 
102,Jason Smith,IT Manager 
103,Raj Reddy,Sysadmin 
104,Anand Ram,Developer

 

! 的用法:在地址范围或模式匹配后 加上 ! 可以表示原条件的相反条件,例如以下示例,如果没有加 ! 则表示打印1、3、5行,但是加上! 后,则表示打印其余的行

$ sed -n '1~2 ! p' employee.txt 
102,Jason Smith,IT Manager
104,Anand Ram,Developer

 


5、Some Other Common commands


  • d:Delete Lines

  the lower case d command deletes the current pattern space, reads the next line from the input-file to the pattern space, aborts the rest of the sed commands and starts the loop again.

  • w:Write Pattern Space to File

sed不会修改原文件的内容,只是修改模式空间中的内容

几个示例:

删除所有行:

sed 'd' employee.txt

删除第2行:

sed '2 d' employee.txt 
101,John Doe,CEO 
103,Raj Reddy,Sysadmin 
104,Anand Ram,Developer 
105,Jane Miller,Sales Manager

删除1到4行:

$ sed '1,4 d' employee.txt 
105,Jane Miller,Sales Manager 

删除奇数行:

$ sed '1~2 d' employee.txt
102,Jason Smith,IT Manager
104,Anand Ram,Developer 

删除第一次出现"Jason"的行到第4行:

$ sed '/Jason/,4 d' employee.txt 
101,John Doe,CEO 
105,Jane Miller,Sales Manager

删除空行:

sed '/^$/ d' employee.txt

删除注释行:

sed '/^#/ d' employee.txt

将employee.txt中的内容逐行写入文件output.txt中:

$ sed 'w output.txt' employee.txt
101,John Doe,CEO 
102,Jason Smith,IT Manager 
103,Raj Reddy,Sysadmin 
104,Anand Ram,Developer 
105,Jane Miller,Sales Manager

把第2行到最后一行的数据写入文件output.txt:

$ sed -n '2,$ w output.txt' employee.txt 

 6、直接修改原文件


我们已经知道了默认sed是不会修改原文件的,为了将修改后的文本写回原文件,可以有以下几种方法:

可以通过w命令将修改后的文本写入一个新文件,然后将新文件重命名为原文件的名字。(注意不能直接使用w命令将新内容写回原文件,否则原文件内容会被清空,达不到效果。)

sed -e '2d' -e 'w output.txt' employee.txt 
mv output.txt employee.txt 

还可以通过标准输出重定向写入一个新文件,然后将新文件重命名为原文件的名字。(注意重定向的文件不能是原文件,否则原文件内容会被清空,达不到效果。)

sed 's/John/Johnny/' employee.txt > new-employee.txt
mv new-employee.txt employee.txt 

以上两种方法都得通过一个中间的文件间接修改,其实可以通过一个选项 -i 来更直接的修改原文件。

$ sed -i 's/John/Johnny/' employee.txt

这样employee.txt的内容就直接被修改了,为了谨慎起见,我们可以通过以下方法在修改原文件前将原文件进行备份

sed -i.bak 's/John/Johnny/' employee.txt 

这样就会首先将原文件备份为employee.txt.bak

posted @ 2013-03-26 11:57  风*依旧  阅读(515)  评论(0编辑  收藏  举报