LFCS 基础：sed 命令
=====================

Linux 基金会认证系统管理员（LFCS）的另一个有用的命令是 “sed”，最初表示“流式编辑器” （Streaming EDitor）。

“sed” 命令是一个可以将文件作为流进行编辑的编辑器。流式传输文件的方法是从另一个命令使用管道（`>` 或 `|`）传递，或将其直接加载到 “sed” 中。

该命令的工作方式与其他编辑器相同，只是文件不显示，也不允许可视化编辑。命令被传递给 “sed” 来操纵流。

用 “sed” 可以做五件基本的事。当然，“sed” 如此强大，还有其他高级的功能，但你只需要集中精力在五件基本的事上。五种功能类型如下：

1.  搜索
2.  替换
3.  删除
4.  添加
5.  改变/变换

在深入命令参数之前，我们需要看看基本的语法。

### 语法

“sed” 命令的语法是：

```
sed [选项] 命令 [要编辑的文件]
```

本文将在适当的部分中介绍这些“选项”。“命令”可以是正则表达式的搜索和替换模式。请继续阅读了解 “sed” 如何工作的并学习基本命令。正如我之前提到的，“sed” 是一个非常强大的工具，有更多的选项可用，我将在本文中介绍。

### 示例文件

如果你打开一个终端，那你可以创建一个用于 “sed” 示例的文件。执行以下命令：

```
cd ~
grep --help >grephelp.txt
```

你现在应该在 HOME 文件夹中有一个名为 `grephelp.txt` 的文件。该文件的内容是 `grep` 命令的帮助说明。

### 搜索

搜索特定字符串是编辑器的常见功能，在 “sed” 中执行搜索也不例外。

执行搜索以在文件中查找字符串。我们来看一下基本的搜索。

如果我们想在示例文件搜索 `PATTERN` 这个词，我们将使用如下命令：

```
sed -n 's/PATTERN/PATTERN/p' grephelp.txt
```

**注意：** 如果剪切粘贴命令，请确保将单引号替换为键盘上的标准单引号。

参数 `-n` 用于抑制每行的自动打印（除了用 `p` 命令指定的行）。默认情况下，流入 “sed” 的每一行将被打印到标准输出（stdout）。如果你不使用 “-n” 选项运行上述命令，你将看到原始文件的每一行以及匹配的行。

要搜索的文件名是我们在“示例文件”部分中创建的 “grephelp.txt”。

剩下的部分是 `'s/PATTERN/PATTERN/p'` 。这一段基本分为四个部分。第一部分的 `s` 指定执行替换，或搜索并替换。

剩下的第二部分和第三部分是模式。第一个是要搜索的模式，最后一个是替换流中匹配字符串的模式。此例中，我们找到字符串 `PATTERN`，并用 `PATTERN` 替换。通过查找和替换相同的字符串，我们完全不会更改文件，甚至在屏幕上也一样。

最后一个命令是 `p`。 它指定在替换后打印新行。当然，因为替换的是相同的字符串，所以没有改变。由于我们使用 `-n` 参数抑制打印行，所以更改的行将使用 `p` 命令打印。

这个完整的命令允许我们执行搜索并查看匹配的结果。

### 替换

当搜索特定字符串时，你可能希望用匹配的字符串替换新字符串。用另一个字符串替换是很常见的操作。

我们可以使用以下命令执行相同的搜索：

```
sed -n 's/PATTERN/Pattern/p' grephelp.txt 
```

在这时，字符串 “PATTERN” 变为 “Pattern” 并显示。如果你使用命令 `cat grephelp.txt` 查看文件，你会看到该文件没有更改。该更改仅对屏幕上的输出进行。你可以使用以下命令将输出通过管道传输到另一个文件：

```
sed 's/PATTERN/Pattern/' grephelp.txt > grephelp1.txt
```

现在将存在一个名为 `grephelp1.txt` 的新文件，其中保存了更改的文件。如果 `p` 作为第四个选项留下，那么有个问题是被替换的字符串的每一行将在文件中重复两次。我们也可以删除 “-n” 参数以允许所有的行打印。

使用相同字符串替换字符串的另一种方法是使用 `&` 符号来表示搜索字符串。例如，命令 `s/PATTERN/&/p` 效果是一样的。我们可以添加字符串，例如添加 `S`，可以使用命令 `s/PATTERN/&S/p`。

如果我们希望在每一行中只替换某种模式呢？可以指定要替换的匹配项的特定出现。当然，每一行的替换都是一个特定的编号。例如，示例文件上有很多破折号。一些行至少有两条破折号，所以我们可以用另一个字符代替每一行的第二个破折号。每行用星号 `*` 替换第二个破折号 `-` 的命令将是：

```
sed 's/-/*/2' grephelp.txt
```

在这里，我们用最初的 `s` 来执行替换。字符 `-` 被替换为 `*`。`2` 表示我们想要替换每行上的第二个 `-`（如果存在）。如果我们忽略了命令 `2`，则替换第一次出现的破折号。只有第一个破折号而不是每行的破折号都被替换。

如果要搜索并替换带有星号的行上的所有破折号，请使用 `g` 命令：

```
sed 's/-/*/g' grephelp.txt
```

命令也可以组合。假设你想要替换从第二次开始出现的破折号，命令将是：

```
sed 's/-/*/2g' grephelp.txt
```

现在从第二个开始出现的破折号将被星号取代。

### 删除

搜索过程中有很多时候你可能想要完全删除搜索字符串。

例如，如果要从文件中删除所有破折号，你可以使用以下命令：

```
sed 's/-//g' grephelp.txt
``` 

替换字符串为空白，因此匹配的字符串将被删除。

### 添加

当找到匹配时，你可以添加一行特定的文本，来使这行在浏览或打印中突出。

如果要在匹配后插入新行，那么使用 `a` 命令，后面跟上新行的字符串。还包括要匹配的字符串。例如，我们可以找到一个 `--`，并在匹配的行之后添加一行。新行的字符串将是 `double dash before this line`。

```
sed '/--/ a "double dash before this line"' grephelp.txt
```

如果要在包含匹配字符串的行之前加上这行，请使用 `i` 命令，如下所示：

```
sed '/--/ i "double dash after this line"' grephelp.txt
``` 

### 改变/变换

如果需要改变/变换一行，则可以使用命令 `c`。

假设我们有个有一些私人信息的文档，我们需要更改包含特定字符串的行。`c` 命令将改变整行，而不仅仅是搜索字符串。

假设我们想要阻止示例文件中包含单词 `PATTERN` 的每一行。更改的行将显示为 `This line is Top Secret`。命令是：

```
sed '/PATTERN/ c This line is Top Secret' grephelp.txt
``` 

可以进行更改特定字母的大小写的转换。例如，我们可以使用命令 `y` 将所有小写 `a` 更改为大写 `A`，如下所示：

```
sed 'y/a/A/' grephelp.txt
```

可以指定多个字母，如 `abdg`，如下命令所示：

```
sed 'y/abdg/ABDG/' grephelp.txt
``` 

确保第二组字母与第一组字母的顺序相同，否则会被替换和转换。例如，字符串 `y/a/D/` 将用大写 `D` 替换所有小写的 `a`。

### 就地更改

如果你确实要更改所使用的文件，请使用 `-i` 选项。

例如，要将 `PATTERN` 改为 `Pattern`，并对文件进行更改，则命令为：

```
sed -i 's/PATTERN/Pattern/' grephelp.txt
```

现在文件 `grephelp.txt` 将被更改。`-i` 选项可以与上述任何命令一起使用来更改原始文件的内容。

练习这些命令，并确保你理解它们。“sed” 命令非常强大。

--------------------------------------------------------------------------------

via: https://www.linux.org/threads/lfcs-sed-command.4561/

作者：[Jarret B][a]
译者：[geekpi](https://github.com/geekpi)
校对：[wxy](https://github.com/wxy)

本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出

[a]:https://www.linux.org/threads/lfcs-sed-command.4561/
