Linux/Unix 中的 Sed 命令及示例

2025年03月17日 | 阅读 9 分钟

Linux 的 'sed' 命令代表流编辑器。它用于使用正则表达式编辑流(文件)。但这种编辑不是永久性的。它只在显示中保留,但实际上,文件内容保持不变。

它主要用于文本替换;此外,它还可以用于其他文本操作,如插入、删除、搜索等。sed 命令允许我们无需打开文件即可编辑文件。正则表达式支持使其成为一个更强大的文本操作工具。

sed 命令概述

它是一个 Unix 实用程序,通过一种紧凑简单的编程语言转换和解析文本。它由贝尔实验室的 Lee E. McMahon 在 1973 年至 1974 年间集成,如今几乎所有操作系统都支持它。sed 命令基于早期 qed(快速编辑器)和 ed 交互式编辑器的脚本方面。它是最早支持正则表达式的工具,并且仍然活跃于文本处理,最重要的是与替换命令一起使用。著名的替代工具包括 Perl 和 AWK,用于“流编辑”和纯文本字符串操作。

sed 命令的操作模式

sed 命令是一个面向行的文本处理实用程序:它逐行从文件或输入流中读取文本到称为模式空间的内部缓冲区。所有行读取都开始一个循环。sed 命令使用 sed 脚本描述的一个或多个操作来处理模式空间。它使用大约 25 个命令的编程语言来描述文本上的操作。

对于所有输入行,sed 命令通常会输出模式空间,并在执行脚本后再次从下一行开始循环。其他脚本结束行为可从脚本命令和设置选项中获得,例如 N 立即将下一行包含到模式空间,q 退出,d 删除模式空间等。因此,sed 脚本与从流线迭代的循环体相关,其中循环变量和循环本身由 sed 维护和隐式。

  • sed 脚本可以在命令行上描述,也可以通过独立文件读取。在 sed 脚本中,命令可以在正则表达式或行号的上下文中采用额外的地址。地址决定了命令何时执行。例如,2d 将仅在第 2 个输入行上执行 d(或删除)命令,而 /^ /d 将删除所有以空格开头的行。
  • 一个独立的特殊缓冲区,即保持空间,可以被某些 sed 命令用于在循环之间保存和累积文本。sed 的命令语言只有两个变量(模式空间和保持空间)和类似 GOTO 的分支功能。然而,该语言是图灵完备的。有用于各种游戏(如俄罗斯方块、国际象棋、打砖块和推箱子)的深奥 sed 脚本。
  • 主循环对输入流的所有行运行,检查输入流所有行上的 sed 脚本。所有 sed 脚本行都是一个模式-动作对,表示要匹配的模式和要实现的动作,可以复制为条件语句。默认动作(打印模式空间、将行复制到模式空间)、输入和输出流以及工作变量(保持空间和模式空间)是隐式的;由于主循环的存在,可以指定简洁的单行程序。

sed 命令的使用

  • 替换命令
    以下示例表示 sed 命令最常用和典型的用法,即替换。此用法是 sed 命令的实际动机。
    sed 's/regexp/replacement/g' inputFileName > outputFileName
  • sed 的其他命令
    使用大约 25 个 sed 命令也可以进行一些简单的处理。例如,下面使用 d 选项来过滤掉只包含空格和行结束符的行。
    sed '/^ *$/d' inputFileName
    上述示例使用了以下几个正则表达式元字符
    • 脱字符 (^) 与行首相同。
    • 美元符号 ($) 与行尾相同。
    • 星号 (*) 与前一个字符出现零次或多次相同。
    • 加号 (+) 与前一个字符出现一次或多次相同。
    • 问号 (?) 与前一个字符出现零次或一次相同。
    • 点符号 (.) 完全等同于一个字符。
  • sed 作为过滤器
    在 Unix 下,sed 命令通常用作管道内的过滤器。
    $ generateData | sed 's/x/y/g'
    generateData 程序生成数据,sed 命令通过将 x 替换为 y 来进行微小更改。
  • 基于文件的 sed 脚本
    通常,将许多 sed 命令(每行一个命令)放入脚本文件中并使用 -f 标志从文件中执行这些命令会很有帮助。
    sed -f subst.sed inputFileName > outputFileName

语法

选项

以下是一些 sed 命令的命令行选项

-n, --quiet, --silent:强制允许我们打印模式空间。

-e script, --expression=script:用于将脚本添加到要执行的命令中。

-f script-file, --file=script-file:用于将 script-file 的内容添加到要执行的命令中。

--follow-symlinks:用于在原地处理时跟随符号链接。

-i[SUFFIX], --in-place[=SUFFIX]:用于原地编辑文件(如果提供了 SUFFIX 选项,则创建备份)。

-l N, --line-length=N:用于指定 'l' 命令所需的行换行长度。

--posix:用于禁用所有 GNU 扩展。

-E, -r, --regexp-extended:允许我们在脚本中使用扩展正则表达式(为了可移植性,请使用 POSIX -E)。

-s, --separate:用于将文件视为单独的文件,而不是单个连续流。

--sandbox:用于在沙盒模式下操作。

-u, --unbuffered:用于从输入文件加载最少量的数据并更频繁地刷新输出缓冲区。

-z, --null-data:用于通过 NUL 字符分隔行。

--help:用于显示帮助手册。

--version:用于显示版本信息。

sed 命令示例

我们来看以下示例

应用于 STDIN 目录

sed 命令不仅限于操作文件;我们还可以将其应用于 STDIN 目录。

上述命令将用第二个文本模式替换第一个文本模式。考虑以下输出

Linux Sed Filter

从上述输出中,我们首先对字符串“class7”执行了 'sed' 命令,其中 'class' 被更改为 'jtp',7 被更改为 10。然后我们对流 'msg.txt' 执行了 'sed' 命令,其中 'learn' 被转换为 'study'。

全局替换

在前面的例子中,并非所有“learn”单词都编辑成了“study”。要编辑每个单词,我们必须使用全局替换 'g'。它将编辑文件或字符串中所有指定的单词。

语法

请看下面的例子

上述命令将替换所有指定的文本模式。请看下面的输出

Linux Sed Filter

从上述输出中,执行命令 "echo class7 class9 | sed 's/class/jtp/g'" 将所有 'class' 转换为 'jtp',执行命令 "cat msg.txt | sed 's/learn/study/g'" 将所有 'learn' 转换为 'study'。

删除一行

'd' 选项允许我们从文件中删除一整行。我们只需要使用 'd' 选项指定该行中的一个单词,该行就会被删除。但是,请注意,所有包含相同单词的行都将被删除。执行方式如下:

考虑以下命令:

上述命令将删除包含单词 'jtp' 的行。请看下面的输出

Linux Sed Filter

从上面的输出可以看出,通过执行命令 "cat msg.txt | sed '/jtp/d'",所有包含单词 'jtp' 的行都被删除了。

使用多个 sed 命令

'-e' 选项允许我们一次执行多个 sed 命令。我们可以通过执行以下命令来执行多个 sed 操作:

考虑以下命令:

上述命令将对文件 'exm.txt' 应用所有指定的操作。请看下面的输出

Linux Sed Filter

从上面的输出中可以看出,所有“red”单词都被替换为“blue”,所有“yellow”单词都被替换为“black”。我们也可以像这样分隔命令:

结果将与上述命令相同。

从文件中读取命令

我们可以将 sed 命令保存在一个文件中,并一次性应用于任何文件。这可以通过指定 '-f' 选项来实现,如下所示:

从上面的命令中,'<sed file>' 是一个包含 sed 命令列表的文件。考虑下面的命令

上述命令将把 'SedCommand' 文件中所有指定的命令应用于 'exm.txt'。请看下面的输出

Linux Sed Filter

从上面的输出中,我们使用了应用于前面示例的命令。因此,输出与前面的示例相同。

替换字符

我们可以使用感叹号 (!) 作为字符串分隔符。例如,我们想要替换 bash shell,并将其替换为 "/etc/passwd" 中的 csh shell。为此,请执行以下命令:

我们可以通过执行以下命令达到相同的效果:

限制 sed

sed 命令的基本用法是处理整个文件。但是,我们可以限制 sed 命令并指定任何行。有两种方法可以限制 sed 命令:

  • 行范围。
  • 匹配特定行的模式。

我们可以通过提供数字来指定行,如下所示

上述命令将对第三行应用指定的操作。请看下面的输出

Linux Sed Filter

从上面的输出可以看出,只有第三行被修改了。

我们还可以指定一个行范围。要指定行范围,请执行如下命令:

上述命令将更新第 1 行和第 3 行中的指定文本。请看下面的输出

Linux Sed Filter

插入和追加文本

'i' 和 'a' 标志用于在文件上插入和追加文本。'i' 标志将在字符串之前添加文本,'a' 标志用于在字符串之后添加文本。请看下面的命令

上述命令将在文本 "Another Demo" 之前插入文本。请看下面的输出

Linux Sed Filter

要追加文本,请执行以下命令:

上述命令将追加文本。请看下面的输出

Linux Sed Filter

修改行

'c' 标志用于修改特定行。要修改行,请执行以下命令

上述命令将更新第三行。请看下面的输出

Linux Sed Filter

我们还可以使用正则表达式来更新多行具有相同模式的行。请看下面的命令

上述命令将更新所有包含字符串“Apple is”的行。请看下面的输出

Linux Sed Filter

字符转换

'y' 标志用于转换字符。字符的转换不能限制在特定的出现次数。要转换字符,请执行以下命令

上述命令将把字符 'a'、'b'、'c' 转换为 'd'、'e'、'f'。请看下面的输出

Linux Sed Filter

打印行号

'=' 符号用于打印行号。要打印行号,请执行以下命令

上述命令将显示文件内容的行号。请看下面的输出

Linux Sed Filter

带有 '-n' 选项的等号指定了包含匹配脚本的行号。请看下面的输出

上述命令将显示包含单词 'mango' 的行号。请看下面的输出

Linux Sed Filter

从上面的输出中,我们可以看到第 2 行有单词 'mango'。


下一个主题Linux tee