Synopsis
sed [options] [range]<command>[;[range]<command>] <target_file>
or:
command_for_sed_input_text | sed [options] [range]<command>
其中range可以是指定行,也可以是一个正则表达式(即所有符合表达式的行),
Options
-
-n: 不显示未处理行,见下面实例;
-
-i: "in-place" edit,见下面的实例;
删除文件中的空行
包括含几个空格、制表符的行:
sed -i '/^\s*$/d' target-file
显示文件的指定部分
例如一个200万行的文件名为error.log,需要从第587700行开始显示200行:
sed -n 587700,587900p error.log
解释:sed的p指令是将匹配到的行显示到终端上,-n是只显示选中的行, 所以使用p指令必加-n选项,-n后面的两个数字分别是起始和终止行号, 最后是要处理的文件名。所以显示文件myfile的第m到第n行的命令是:
sed -n m,np myfile
如果要显示的行是不连续的,需要用多个"-e"选项, 例如下面的命令打印input.txt文件的第1~10行,第53行和第200行:
sed -ne 1,10p -e 53p -e 200p input.txt
在文件的指定行前插入一行
在文件distro.txt第7行前插入一行"ab cd":
sed -i '7 i ab cd' distros.txt
"-i"表示结果写回原文件,而不是打印到stdout, 即"in-place" edit。同理,在第7行后加一行就是:
sed -i '7 a ab cd' distros.txt
把第7行替换为"ab cd":
sed '7 c ab cd' distros.txt
将多个编辑操作放在一个sed命令中进行
$ cat aaa
the first line
the 2nd line
last line
$ sed -e '1 a new line' -e '2 d' aaa
the first line
new line
last line
首先,多个操作用"-e"选项组合在一起,其次,每个操作中的行指的是原始文件的行, 而不是前面操作之后新的行,上面例子中第一个操作是在第一行后插入一行, 然后删掉第2行,可以看到删掉的是原文件的第2行,而不是新插入的行。
使用正则表达式处理多个行
$ sed '/.*line/ a abc' aaa the first line abc the 2nd line abc last line abc
输出指定区域的文本
有一个配置文件,现在想输出小节名称和后面的两行文本:
$ cat puppet.conf
[main]
The Puppet log directory.
The default value is '$vardir/log'.
logdir = /var/log/puppet
Where Puppet PID files are kept.
...
[agent]
The file in which puppetd stores a list of the classes
associated with the retrieved configuratiion. Can be loaded in
the separate ``puppet`` executable using the ``--loadclasses``
option.
The default value is '$confdir/classes.txt'.
classfile = $vardir/classes.txt
...
$ sed -n '/\[.*/,+2p' puppet.conf
[main]
The Puppet log directory.
The default value is '$vardir/log'.
[agent]
The file in which puppetd stores a list of the classes
associated with the retrieved configuratiion. Can be loaded in
这里使用了"
文件末尾操作
sed的行号中,"$"代表最后一行,所以下面两句是等价的:
sed '$ a abcd' aaa
echo "abcd" >> aaa
但sed显然功能更强,比如可以用'$ i ...'实现在最后一行前面插入。
替换一行的指定部分
要把数据库地址改为mdb
,也就是把mongodb://
与:27017...
之间的部分改成mdb
,
方法是将要保留的部分放在正则表达式的group里,
替换的时候用backreference恢复要保留的部分,
\1
是前段,\2
是后段,中间被替换的部分改为mdb
:
$ cat default.json
{
"db": {
"address": "mongodb://dba:dba@192.168.100.3:27017/staging",
"collection": "Schedule2"
}
}
$ sed -i -r 's%(.*"address": "mongodb://).*(:27017.*)%\1mdb\2%' default.json
$ cat default.json
{
"db": {
"address": "mongodb://mdb:27017/staging",
"collection": "Schedule2"
}
}
由于文本中有/
,所以sed的替换分隔符改成了%
。
-i
的作用是修改原文件,-r
的作用是不需要为替换表达式中的括号转义。
参考:http://stackoverflow.com/questions/1074450/sed-replace-part-of-a-line