sed 是一种UNIX/LINUX 平台下的轻量级流编辑器,日常一般用于处理文本文件。sed 有许多很好的特性。首先,它相当小巧;其次, sed 可以配合强大的 shell 完成许多复杂的功能。在我看来,sed完全可以看成一个脚本解释器,用类似于编程的手段完成许多事情。
sed简单示例
sed命令的格式是
sed [-options] [command] [stdin]
比如这个例子
$ sed –e ‘d’ ./Mydir/Myfile
执行该命令,将得不到任何输出。在该例中,用一个编辑命令 'd' 调用 sed;sed 打开 ./Mydir/Myfile 将一行读入其模式缓冲区,执行’d’(“删除行”);然后打印模式缓冲区(缓冲区已为空);它对后面的每一行重复这些步骤,这不会产生输出!
对
这个命令要说明的几点是:首先,它根本没有修改 ./Mydir/Myfile。这是因为 sed
是流处理器,它只读取在命令行指定的文件,它不试图修改该文件。其次, sed 是面向行的,'d' 命令不是简单地告诉 sed
一下子删除所有输入数据;相反,sed 逐行将 ./Mydir/Myfile
的每一行读入其称为模式缓冲区的内部缓冲区,一旦将一行读入模式缓冲区,它就执行 'd' 命令,然后打印模式缓冲区的内容。最后要注意的事是括起
'd' 命令的单引号的用法,这样可以禁用 shell 扩展。
指定sed的作用范围
看下面的三个例子
$ sed –e ‘1d’ ./Mydir/Myfile
$ sed –e ‘1,10d’ ./Mydir/Myfile
$ sed –e ‘/begin/,/end/p’ ./Mydir/Myfile
第一个例子说明只删除./Mydir/Myfile第一行的缓冲,第二个例子将删除第1~10行的缓冲。第三个例子最复杂,它定义了以字符串’begin’开始到’end’结束的作用范围
sed中的正则表达式
sed支持正则表达式,比如
$ sed –n -e ‘/regexp/p’ ./Mydir/Myfile
比如要删除所有的空行
$ sed –e ‘/^$/d’ ./Mydir/Myfile
sed中的一些特殊定义是
规则 表达式 描述
/./ 将与包含至少一个字符的任何行匹配
/../ 将与包含至少两个字符的任何行匹配
/^#/ 将与以 '#' 开始的任何行匹配
/^$/ 将与所有空行匹配
/}^/ 将与以 '}'(无空格)结束的任何行匹配
/} *^/ 将与以 '}' 后面跟有 零或多个空格结束的任何行匹配
/[abc]/ 将与包含小写 'a'、'b' 或 'c' 的任何行匹配
/^[abc]/ 将与以 'a'、'b' 或 'c' 开始的任何行匹配
再比如一个经典的例子,打印c源代码中的main函数内容,其命令可以写成如下
$ sed –n –e ‘/main[[:space]]*(/,/^}/p’ ./Mydir/*.c
其中[:space]表示空格,[[:space]]*表示有0~多个空格,所以main[[:space]]*(的意思是匹配“main (”字符串;“^}”表示这一行有且只有一个字符}。当然,上面的命令不是十分严谨。
sed –e ‘s/regexp/repalcement’ file
替换是sed命令中最常用的命令,比如如下的例子
$ sed –e ‘s/a/b’ ./Mydir/Myfile
$ sed –e ‘s/a/b/g’ ./Mydir/Myfile
第一个命令将./Mydir/Myfile中每一行第一次出现的字符a替换成字符b;第二个命令由于加入了’/g’,表示是全局(全部)替换字符a成字符b。
经常还可以看见如下两种形式的sed
$ sed –e ‘1,10s/a/b’ ./Mydir/Myfile
$ sed –e ‘/^$/,/^END/s/a/b/g’ ./Mydir/Myfile
第一个命令是指替换1~10行;第二个命令是指全局替换从空行开始到以END开始的行中的内容。
替换命令不一定非要以/分隔,比如
$ sed –e ‘s:usr/local:/usr:g’ ./Mydir/Myfile
就是将./Mydir/Myfile中的usr/local全部替换成/usr
要用好替换命令,当然要使用正则表达式,除了上面所说的表达式的例子,还有一些是非常有用的
字符类 描述
[: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 –e ‘s/<[^>]*>//g’ ./Mydir/Myfile
<
[^>]*>匹配<…>这样的字符串(…中不含>)。运行这个命令,能够将
“<b>This</b> is what <b>I</b>
meant.”这样的字符串替换成“This is what I meant.”
考察如下的命令
$ sed -e 's/.*/# &/' ./Mydir/Myfile
这个命令将所有的非空行以“#”注释掉——&告诉sed在行首插入字符。
‘s///’允许我们在规则表达式中定义区域,然后可以在替换字符串中引用这些特定区域。这些区域是以(和)隔开的。
比如定义三个匹配非空字符的区域'(.*) (.*) (.*)',现在可以定义这三个区域的动作,比如
$ sed -e 's/(.*) (.*) (.*)/PreFix 1-2 Fix 3/' ./Mydir/Myfile
假如把三个区域分别命名为a、b、c,则最后结果是 PreFix a-b Fix c
sed中组合命令
sed中的命令可以组合,以;号隔开,比如
$ sed –n –e ‘=;p’ ./Mydir/Myfile
=表示打印行号,p表示打印。对于更复杂的指令,则可以写成命令脚本,然后用-f选项导入,比如
$ sed –n –f MyScript.sed ./Mydir/Myfile
对于同一个地址上的操作,则可以用{}组合,比如
$ sed –n ‘1,20{ s/samba/Samba/g s/posix/POSIX/g }’ ./Mydir/Myfile
sed中的行附加命令
在当前行之前插入行“i”,如果要插入多行,则将多行用分隔
在当前行之后插入行“a”,用法和上面相似
更改当前行“c”
-- The End --