sed 替换基础

LinuxBeginner
立即练习

简介

文本处理中一个常见的任务是「查找和替换」。在文字处理器中,这通常通过交互方式完成;在 Linux 命令行环境中,sed 以可编写脚本、无需交互的方式实现相同的功能。

sed 是一个非交互式文本编辑器,会逐行处理文本。它特别适合执行替换任务,例如将指定模式替换为新文本。在自动化场景中,这非常有用,因为不需要人工反复打开编辑器执行相同的修改。

在本实验中,你将学习:

  1. 替换文本(s):执行基本的查找和替换操作。
  2. 全局替换(g):替换一行中某个模式的所有匹配项,而不只是第一个匹配项。
  3. 使用自定义分隔符:使用其他分隔符处理包含斜杠的文本,例如文件路径。
  4. 创建备份并原地编辑:自动创建备份副本,从而更安全地修改文件。

基本替换

先对字符串执行一个简单的替换,将单词「World」改为「Linux」。

sed 中用于替换的命令是 s。

语法为 s/Pattern/Replacement/。

这种命令形式非常常见,因此许多用户会把 sed 视为「查找和替换工具」。但实际上,sed 是一个流编辑器,而替换只是它最常用的编辑命令之一。

运行以下命令查看效果:

echo "Hello World" | sed 's/World/Linux/'

工作原理:

  1. echo 将「Hello World」发送到标准输出。
  2. 管道 | 将该输出传递给 sed。
  3. sed 读取文本,查找模式「World」,将其替换为「Linux」,然后打印结果。

注意:此命令不会永久修改原始数据;它只会将修改后的文本输出到屏幕(标准输出)。

理解这一点对于安全地进行命令行编辑非常重要。在 Unix 风格的操作中,工具通常会先显示转换后的数据流,之后再由你决定是否保存或重定向结果。

全局替换

默认情况下,sed 只会替换每一行中找到的第一个匹配项。

如果文本是「apple apple」,将「apple」替换为「orange」后,sed 会输出「orange apple」。

要替换一行中的所有匹配项,必须在替换命令末尾使用全局标志(g)。

需要特别注意的是「每一行」。sed 一次处理一行,因此 g 标志会影响当前行中的所有匹配项,而不是把整个文件作为一个巨大的文本块进行处理。

先查看示例文件 quote.txt:

cat quote.txt

输出:I love Coding. Coding is fun.

现在不使用全局标志,将「Coding」替换为「Programming」:

sed 's/Coding/Programming/' quote.txt

结果:I love Programming. Coding is fun.
注意,第二个「Coding」没有被替换。

现在添加 g 标志:

sed 's/Coding/Programming/g' quote.txt

结果:I love Programming. Programming is fun.
现在两个匹配项都已成功替换。

使用不同的分隔符

标准的 sed 语法使用正斜杠 / 作为分隔符:s/old/new/。

但是,如果要替换的文本包含斜杠,例如文件路径 /usr/local/bin,就必须使用反斜杠转义每个斜杠。这样会使命令难以阅读:s/\/usr\/local\/bin/\/bin/。

幸运的是,sed 允许使用几乎任何字符作为分隔符。常见的替代分隔符包括 #、: 和 |。

选择易读的分隔符是一项实用技能,而不仅仅是语法技巧。当模式中包含许多 / 字符时,更换分隔符可以让命令更容易理解,也能减少出错的可能。

创建一个包含路径的文件:

echo "/usr/local/bin" > path.txt

现在使用 # 作为分隔符,将 /usr/local/bin 替换为 /bin:

sed 's#/usr/local/bin#/bin#' path.txt

结果:/bin

由于使用了 # 作为分隔符,sed 会将路径中的 / 字符视为普通文本,因此命令更加简洁、易读。

创建备份并原地编辑

到目前为止,sed 只会将修改结果打印到屏幕。要直接修改文件(即「原地」修改),请使用 -i 选项。

但是,直接修改文件存在风险。如果模式写错,可能会丢失数据。更理想的做法是在修改文件前创建原始文件的备份。

为此,可以向 -i 选项提供扩展名,例如 -i.bak。

修改 quote.txt,并自动创建名为 quote.txt.bak 的备份:

sed -i.bak 's/fun/awesome/' quote.txt

现在查看修改后文件的内容:

cat quote.txt

结果:I love Coding. Coding is awesome.

然后确认备份文件存在,并检查其中是否保留了原始文本:

ls -l quote.txt.bak
cat quote.txt.bak

结果:I love Coding. Coding is fun.

对多个文件执行批量编辑时,建议采用这种做法。

这是因为非交互式编辑速度很快,但出错后不会主动提醒。当你自动化替换多个文件中的文本时,一个小小的模式错误可能会迅速扩散,因此保留原始副本是一种简单有效的安全措施。

总结

在本实验中,你学习了使用 sed 替换文本的基础知识:

  1. 替换(s///):用于查找和替换文本的标准命令。
  2. 全局标志(g):替换一行中某个模式的所有匹配项。
  3. 自定义分隔符:使用 # 等字符安全处理包含 / 的路径和 URL。
  4. 原地编辑并创建备份(-i.bak):在保留原始内容的同时安全地修改文件。

掌握这些技能后,你就能更高效、更安全地自动化复杂的文本处理任务。