sed是一个非常非常强大的命令行编辑器,说是编辑器,还不如说是编辑程序,因为它是面向流的(没有GUI),看起来比较土,但是功能却一点也不含糊,在*nix下的shell中工作,如果有这个东东帮忙,可以少做不少事(尤其是程序员所讨厌的那种重复动作)
首先,sed是一个面向行的流编辑器,所以使用方法一般是通过shell中的管道,基本起一个过滤的作用(不是简单的过滤),sed对原始文件不会修改,因此可以完全“安全,无副作用”的使用。
使用方式:
管道符后边为其他一些命令,如more|less(查看)等
1.简单示例
sed可以从一个地址范围中,做某些指定的操作,如删除一个文件的第100行到300行,很简单
$sed -e "100,300d" file
即可
sed的表达式一般为 range+command, 或者pattern+command,其中range表示一个范围,range的两个端点之间用逗号分隔开来。
2.使用正则表达式
*nix中的大部分支持正则表达式的工具中,正则表达式的写法一般为/regex/,当然这个/在通常情况下都是好用的,但是,如果在pattern(模式)本身就有很多/字符的情况下,则需要通过转义字符来转义。(特别是目录操作,*nix中,目录分隔符为/)
稍微高级一点的正则表达式工具都支持使用不同的分隔符来表示正则表达式的分隔。如冒号":",逗号","等。
比如,要从一个web页面中提取出所有的javascript脚本,则可以使用
$sed -ne "/<script.*>/,/<\/script>/p" web.html | less
此处的n也是一个sed参数,表示安静模式,自动输出匹配串
删除一个脚本文件中的所有注释,(在*nix系统中,脚本文件通常以#开头的行为注释)
$sed -e "/^#/d" script
3.查找替换
$sed -e "s/foo/bar" file
s表示search,foo为一个正则表达式,bar为需要被置换成的串replacement
此命令只是用bar替换每一行第一次出现的foo,如果需要完全替换
$sed -e "s/foo/bar/g" file
g表示global
当然,如此强大的编辑器不可能没有范围的定制参数,如,一个文件file中,第100到第150行中,所以的foo需要被替换成bar
$sed -e "100,150s/foo/bar/g" file
即可。
一般情况下,*nix系统下的命令都遵循很多的约定,一个参数在一个程序中表示的意义通常在另一个程序中表示同样的意义。(如果你会使用vim的话,会发现,sed的命令大部分与vim的编辑模式是一模一样的)
java或者vim中,关于下列列出来的正则表达式缩写有更好的解决方法,不过sed中使用的是这样一个比较奇特的格式:
字符类 | 描述 |
[:alnum:] |
字母数字 [a-z A-Z 0-9] |
[:alpha:] | 字母 [a-z A-Z] |
[:blank:] | 空格或制表键 |
[:cntrl:] | 任何控制字符 |
[:digit:] | 数字 [0-9] |
[:graph:] | 任何可视字符(无空格) |
[:lower:] |
小写 [a-z] |
[:print:] | 非控制字符 |
[:punct:] | 标点字符 |
[:space:] |
空格 |
[:upper:] | 大写 [A-Z] |
[:xdigit:] |
十六进制数字 [0-9 a-f A-F] |
涉及到正则表达式的替换的时候,必须提到组的概念,这就是为什么sed的正则命令中的'&'字符的用途.
如,将一个脚本文件的所有行变成注释,可以使用下面这样的命令
$sed -e "s/.*/# &/g" script
这里的&表示正则表达式匹配到的字串
当然,sed的分组支持不止这些,将需要匹配的pattern用圆括号括起来,sed依次给这些组编号,\1为第一组,\2为第二组,以此类推。注意,'&'表示整个匹配。如果使用的script比较大,比较复杂,那么最好将其放入一个单独的文件:
$sed -nf command.sed file.txt
如果,需要执行多次查找替换功能,不需要依次敲入命令,只需要将这些模式放入一个大括号就可以了,如
$sed -ne "1,200{s/foo1/bar1/g s/foo2/bar2/g s/foo3/bar3/g}" file
*nix的哲学中讲究这样一点:程序最好是面向文本的(输入/输出均为文本流),这样很容易和其他的程序进行整合,从而实现比较强大的功能。当然,这里介绍的sed的命令都是一些比较基本,比较简单的功能,如果我在实践中发现更好的命令或者比较高级的用法,会再陆续的补充出来。