LinuxShell命令sed

1. 简介

sed 是 Linux系统自带的流式编辑器(流式编辑器是指处理处理输入流或文本流中的数据),不同于普通的交互式文本编辑器(比如 vim),sed 编辑器根据命令来处理数据流中的数据。

sed 默认不会直接修改源文件,而是将读入的数据先复制到模式空间(pattern space)中缓存,再根据给定的命令对模式空间中的数据进行处理并输出(默认 STDOUT)。

2. 运行机制

  • 一次从输入中读取一行数据
  • 根据提供的命令匹配数据流中的数据
  • 按照命令修改数据流中的数据
  • 将处理后的数据输出到STDOUT

3. 命令格式

1
sed [options]... {script} [file]...

【注】命令行中输入 sed 脚本命令 script 需用两个单引号 ' ' 或者两个双引号 " " 引起来。使用两个单引号时,script 中使用 / 分隔每个字段,字段均为纯字符串,不能使用 Shell 下的变量;使用两个双引号时,script 中使用 | 分隔每个字段,字段中可以使用 Shell 下的变量。

4. 常用选项

  • -n--quite--slient :使用安静模式屏蔽输出(默认情况下,sed 如上图所示输出数据)
  • -e script--expression=script :将 script 中指定的命令添加到将要执行的命令中(多个命令之间用 ; 分隔)。
  • -f script-file--file=script-file :将 script-file 中的内容添加到将要执行的命令中(一条命令占一行,无需分号 ;)。
  • -i[SUFFIX]、--in-place[=SUFFIX] :在原文件上就地编辑(如果提供 SUFFIX 后缀名,sed 将备份原文件并以原文件名拼接 SUFFIX 命名。
  • -E-r--regexp-extended :在 sed 脚本命令中使用ERE(extended regular expression,扩展正则表达式)引擎。

【注】sed 编辑器只符合了BRE(basic regular expression,基础正则表达式)引擎规范的子集。详情请参阅正则表达式

5. 常用命令

  • = :打印当前行的行号。
  • # :注释该行 # 后的所有内容。
  • & :代表替换命令中匹配到的模式。
  • $ :代表数据流中的最后一行(也可直接用数字指定行,用 x,y 指定第 x 到第 y 行)。
  • \( regexp \) :定义了替换模式中的子模式(之后可用 \x 来引用第 x 个匹配的子模式)。当 sed 使用了 ERE 引擎后,子模式按照 ERE 中的规范为 ( ),不再需要转义。
  • {} :组合多条 sed 脚本命令(多条脚本命令用 ; 分隔)。
  • a\ text :在指定行后追加内容为 text 的新行。
  • i\ text :在指定行前追加内容为 text 的新行。
  • r\ file :从 file 文件中读取内容并追加到模式空间匹配到的行后。
  • b [label] :处理到指定行后跳转到 sed 命令脚本 label 处(若未指定 label 参数,则跳转到脚本结尾)。
  • t [label] :替换命令成功匹配替换后跳转到 sed 命令脚本 label 处(若未指定 label 参数,则跳转到脚本结尾)。
  • T [label] :替换命令未成功匹配替换后跳转到 sed 命令脚本 label 处(若未指定 label 参数,则跳转到脚本结尾)。
  • c\ text :用 text 替代匹配到的行。
  • d :清空模式空间中的数据。
  • D :删除模式空间中的第一行(包括换行符)。
  • h :复制模式空间到保存空间。
  • H :追加模式空间到保存空间。
  • g :复制保存空间到模式空间。
  • G :追加保存空间到模式空间。
  • n :读取下一行到模式空间。
  • N :追加下一行到模式空间。
  • p :打印模式空间中的数据。
  • P :打印模式空间中的第一行(包括换行符)。
  • l :打印所有字符(不可打印字符要么在其八进制值前加 \,要么使用标准的 C 风格命名法)。
  • s/regexp/replacement/flags :用单引号引起,在模式空间中用 replacement 替代 flags 处的 regexpreplacementregexp 均为纯字符串(可以包含转义字符),不能使用 Shell 下的变量(即不会解释 Shell 下的变量)。
  • s|regexp|replacement|flags :用双引号引起,在模式空间中用 replacement 替代 flags 处的 regexpreplacementregexp 可以使用 Shell 下的变量。

【注】flags 可为以下四种(可直接拼接叠加使用):

  1. 数字 :指明替换第几处的 regexp
  2. g :表明替换所有的 regexp
  3. p :表明打印匹配到的模式空间中处理后的内容
  4. w file :将替换后的数据写入 file 文件
  • w file :将当前模式空间中的数据写入 file 文件。
  • W file :将当前模式空间中的第一行(包括换行符)写入 file 文件。
  • x :交换模式空间和保持空间的数据。
  • y/schars/dchars/ :对模式空间中任何在 schars 中出现的字符一一映射到 dchars 对应位置的字符(故 scharsdchars 的长度要求一致)。

【注】追加数据行到模式空间时,数据行之间仍用换行符分隔,但 sed 编辑器会将整个模式空间中的数据当做一行处理。

6. 举例

  • 打印 XXX 文件中第 5 行及其后的所有行:
1
sed -n '5,$p' XXX
  • XXX 文件数据中的第 2 行删除后写入 YYY 文件:
1
sed -n '2d; w YYY' XXX
  • XXX 文件数据中的空白行替换成 text 并回写入 XXX 文件中:
1
sed -i 's/^$/text/' XXX
  • 使用 sed 从命令脚本文件中读取命令来将数据中的 X、Y、Z 依次替换为 x、y、z:

(1)创建一个包含以下 sed 命令的脚本文件 script.sed

1
2
3
s/X/x/g
s/Y/y/g
s/Z/z/g

(2)然后使用 sed 读取该脚本文件来处理数据:

1
echo "XYZZYX" | sed -f script.sed

(3)显示结果如下:

1
xyzzyx
  • 将 github 仓库的 https 协议链接转换成 ssh 协议链接:
1
sed -Ei 's/http[s]?:\/\/[^[:space:]\/]+\/([^[:space:]]+)/git@github.com:\1/' testfile

其中,testfile 为包含 github 仓库的 https 协议链接的文件。

  • 借助 Shell 下的环境变量替换 xxx.conf 中的下载路径:
1
sed -i "s|^dir=\/root\/Download$|dir=${HOME}\/Downloads|" xxx.conf