大多数情况下,对于文件内容的修改需要依赖交互式的软件来实现,例如vim修改文件的内容则是依赖光标的移动和修改操作来完成对文件某一处内容的修改。然而,在linux操作系统中,也存在一种非交互式的方法来修改文件内容,通过发送特殊的指令给终端使其完成对特定内容文件的修改。

sed(Stream editor)正是一种非交互的流式编辑器。sed支持修改一个输入流(文件或管道)中的文本或字段的值,且因为只会对输入的流文件进行一次处理,因此sed的工作效率要比其他的编辑器更加高效。而能够从管道(Pipeline)中获取过滤输入流,这也是sed相比其他编辑器的显著区分。

语法

sed [OPTION]... {script-only-if-no-other-script} [input-file]...

参数含义

  • -n, --quiet, --silent: 抑制命令执行过程中的打印信息
  • -e script: 指定的脚本中的命令将被执行
  • -f script-file: 指定的脚本文件中是sed的编辑命令
  • --follow-symlinks: 对于链接文件,替换的时候源文件也会进行替换
  • -i[SUFFIX]: 编辑文件进行替换(如果提供了SUFFIX,则进行备份)。默认没有指定 -i 的情况下,sed只将指令的结果打印到终端,不会修改文件的内容。
  • -c, --copy: 使用-i选项的时候用复制代替重命名
  • --posix: 禁用GUN扩展
  • -r: 使用扩展正则表达式

替换标记

  • g: 替换每行中匹配到的所有字符
  • p: 打印被sed程序处理过的行
  • d: 指定行将被删除
  • s: 替换指定字符串

详细用法

  • 删除文件中指定的行
#wc -l /tmp/passwd
39 /tmp/passwd

#sed -i '11,39d' /tmp/passwd    # 删除11-39行的记录 && 指令-i后才会修改文件

#wc -l /tmp/passwd
10 /tmp/passwd
  • 删除文件的最后一行
#sed -i '$d' /tmp/passwd

#wc -l /tmp/passwd
9 /tmp/passwd
  • 删除文件中的匹配行
#sed -i '/nologin$/d' /tmp/passwd       # nologin$ 表明匹配以nologin结尾的行; 对应的 ^nologin 表明以nologin为首的行

#wc -l /tmp/passwd
4 /tmp/passwd
  • 删除输入流中的空行
#sed -i '/^$/'d /tmp/passwd
  • 替换一行中的第一个匹配到的字符串
#cat -n /tmp/passwd
     1  root:x:0:0:root:/root:/bin/bash
     2  bin:x:1:1:bin:/bin:/sbin/nologin
     3  daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4  adm:x:3:4:adm:/var/adm:/sbin/nologin
     5  lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6  sync:x:5:0:sync:/sbin:/bin/sync
     7  shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8  halt:x:7:0:halt:/sbin:/sbin/halt
     9  mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10  operator:x:11:0:operator:/root:/sbin/nologin

#sed -n 's/mail/exchange/p' /tmp/passwd
exchange:x:8:12:mail:/var/spool/mail:/sbin/nologin
  • 替换一行中所有匹配到的字符串
#sed -n 's/mail/exchange/gp' /tmp/passwd
exchange:x:8:12:exchange:/var/spool/exchange:/sbin/nologin
  • 从每行匹配到的第2处开始替换
#sed -n 's/mail/MAIL/2p' /tmp/passwd
mail:x:8:12:MAIL:/var/spool/mail:/sbin/nologin
  • 在指定行前增加一条记录说明: 使用sed对文件进行插入内容时,仅对有行数的文件有效;类似于空文件(没有行记录),插入操作无效
#sed '2 i\***********************  ' /tmp/passwd
root:x:0:0:root:/root:/bin/bash
***********************
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
  • 在指定行后增加一条记录
#sed '2 a\***********************  ' /tmp/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
***********************
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
  • 通过管道接收上一条命令的输出并修改命令输出结果
#echo $LANG
en_US.UTF-8

#echo $LANG | sed  's/en_US/zh_CN/'
zh_CN.UTF-8
  • 注释文件中的所有行
#sed -i 's/^/#/' /tmp/passwd

#cat /tmp/passwd
#root:x:0:0:root:/root:/bin/bash
#sync:x:5:0:sync:/sbin:/bin/sync
#shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
#halt:x:7:0:halt:/sbin:/sbin/halt
  • 删除文件中每行的第一个字符
#sed -i 's/^.//1' /tmp/passwd

#cat /tmp/passwd
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
  • 根据匹配到的内容注释指定的行
#sed -n 's/root/#root/p' /tmp/passwd
#root:x:0:0:root:/root:/bin/bash