Linux 常用命令 SED

2014-03-21 linux command

sed 是一个精简的、非交互式的编辑器,可以提供与编辑器 VIM 或者 EMACS 相同的编辑任务,但 sed 不提供交互使用方式,只能在命令行下输入编辑命令。

这里简单介绍其使用方法。

简介

常用操作如下。

sed 默认会打印所有的处理行,可以通过 -n 参数取消默认的打印,例如,可以通过 /Pattern/p 参数,那么此时只会打印匹配的行。

----- 全局替换匹配行,s 替换,g 全局
$ sed -i 's/^a.*/haha/g' filename

----- 文件头部添加一行,命令1表示第一行,i表示插入,之后是内容
$ sed -i "1ifoobar" filename
  i 行前插入 insert
  a 行后插入 append
  c 行替换   change
----- 规则匹配行前插入
$ sed -i "/foobar/ifoo" filename

----- 删除指定行,$表示最后一行
$ sed -i '1d' filename
$ sed -i '$d' filename
$ sed -i '/foobar/d' filename

注意,通过 -i 参数会直接替换原文件的内容,否则只会在打印的信息中进行相关处理,而非修改原文件。

可以通过如下命令删除两个标记行之间的内容,相关帮助可以通过 info sed 查看。

----- 查看输出,没有问题直接替换
$ sed '0,/^#YOUR-MARK-BEGIN$/{//d;b};0,/^#YOUR-MARK-END$/d'    # 只删除第一个匹配
$ sed '/^#YOUR-MARK-BEGIN$/, /^#YOUR-MARK-END$/d'              # 删除所有匹配
$ sed -i -e '0,/^#YOUR-MARK-BEGIN$/{//d;b};0,/^#YOUR-MARK-END$/d'

示例

crontab 替换

因为会涉及到文件路径,而其中的匹配字符 / 会与其冲突,可以使用 % ,示例如下。

----- 只替换文件的路径
sed -i -n 's%/Your/File/Path%/Your/New/File/Path%g' /etc/crontab
----- 替换整行
sed -i -n 's%^.* /Your/File/Path .*$%* */5 * * * root /Your/New/File/Path >/dev/null 2>\&1%g' /etc/crontab

当然,也可以先删除,然后再在最后一行添加。

sed -i '/\/Your\/File\/Path/d' /etc/crontab
sed -i '$a * */10 * * * root /Your/New/File/Path >/dev/null 2>&1' /etc/crontab

注意,如果是只打印,没有找到太好的方法。

sed -n '/\/Your\/File\/Path/g' /etc/crontab

多行替换

sed 经常用来替换文件的内容,通常是处理单行的,但通过它的一些内建功能,也能实现多行替换。假设有如下的文本:

  hello <<<comment part 1
  comment part 2>>>
  foobar

现在需要把 <<< ... >>> 这一段替换为 “COMMENT”,那么 sed 语法应当是:

:begin
/<<</,/>>>/ {
    />>>/! {
        $! {
            N;
             b begin
        }
    }
    s/<<<.*>>>/COMMENT/;
}

上述语句存储在 test.sed 中,那么执行的方式和结果就是:

$ sed -f foobar.sed foobar
  hello COMMENT
  foobar

把正则直接写到命令里面也可以,用 ";" 来分隔命令即可,注意右花括号之后也要加上分号 ";",如果再加上 -i 参数就可以直接把改动写到原文件中去了:

$ sed -e ":begin; /<<</,/>>>/ { />>>/! { $! { N; b begin }; }; s/<<<.*>>>/COMMENT/; };" test
  hello COMMENT
  foobar

各个步骤介绍如下:

  1. 花括号 {} 代表命令块的开始,类似 C 语法;
  2. :begin 是一个标号 (label),用于跳转,供 b、t、T 等命令使用,这里使用了 b 命令;
  3. /<<</,/>>>/ 通过逗号分隔 (开始+结束位置) 用于标示地址范围,后面 {} 中的命令只对地址范围之间的内容使用。
  4. />>>/! $! 其中叹号表示取反,而 $ 在 sed 中表示为最后一行,也就意味着 “如果在本行没有发现结束标记,而且本行不是文件的最后一行” 那么执行下面的操作;
  5. N; 用于把下一行的内容追加到缓冲区 (pattern),也就是相当于合并为一行;
  6. b begin 由于仍然没有找到结束标记跳回到 begin,重新执行追加命令;
  7. s/<<<.*>>>/COMMENT/; 匹配完成之后,可以通过该命令替换。

参考

详细内容可以查看官方手册 sed, a stream editor 中的内容。