使用 sed 命令进行复制、剪切和粘贴
sed 复制 粘贴

> 
> 了解 sed 的基本用法，然后下载我们的备忘单，方便快速地参考 Linux 流编辑器。
> 
> 
> 


![](/data/attachment/album/202105/23/181625abgrg4dsbw4y4fue.jpg "Penguin with green background")


很少有 Unix 命令像 `sed`、[grep](https://opensource.com/article/21/3/grep-cheat-sheet) 和 [awk](https://opensource.com/article/20/9/awk-ebook) 一样出名，它们经常组合在一起，可能是因为它们具有奇怪的名称和强大的文本解析能力。它们还在一些语法和逻辑上有相似之处。虽然它们都能用于文本解析，但都有其特殊性。本文研究 `sed` 命令，它是一个 <ruby> 流编辑器 <rt>  stream editor </rt></ruby>。


我之前写过关于 [sed](https://opensource.com/article/20/12/sed) 以及它的远亲 [ed](https://opensource.com/article/20/12/gnu-ed) 的文章。要熟悉 `sed`，对 `ed` 有一点了解是有帮助的，因为这有助于你熟悉缓冲区的概念。本文假定你熟悉 `sed` 的基本知识，这意味着你至少已经运行过经典的 `s/foo/bar` 风格的查找和替换命令。


* 下载我们的免费 [sed 备忘录](https://opensource.com/downloads/sed-cheat-sheet)


### 安装 sed


如果你使用的是 Linux、BSD 或 macOS，那么它们已经安装了 GNU 的或 BSD 的 sed。这些是原始 `sed` 命令的独特重新实现。虽然它们很相似，但也有一些细微的差别。本文已经在 Linux 和 NetBSD 版本上进行了测试，所以你可以使用你的计算机上找到的任何 sed，但是对于 BSD sed，你必须使用短选项（例如 `-n` 而不是 `--quiet`）。


GNU sed 通常被认为是功能最丰富的 sed，因此无论你是否运行 Linux，你可能都想要尝试一下。如果在 Ports 树中找不到 GNU sed（在非 Linux 系统上通常称为 gsed），你可以从 GNU 网站 [下载源代码](http://www.gnu.org/software/sed/)。 安装 GNU sed 的好处是，你可以使用它的额外功能，但是如果需要可移植性，还可以限制它以遵守 sed 的 [POSIX](https://opensource.com/article/19/7/what-posix-richard-stallman-explains) 规范。


MacOS 用户可以在 [MacPorts](https://opensource.com/article/20/11/macports) 或 [Homebrew](https://opensource.com/article/20/6/homebrew-mac) 上找到 GNU sed。


在 Windows 上，你可以通过 [Chocolatey](https://opensource.com/article/20/3/chocolatey) 来 [安装 GNU sed](https://chocolatey.org/packages/sed)。


### 了解模式空间和保留空间


sed 一次只能处理一行。因为它没有可视化模式，所以会创建一个 <ruby> 模式空间 <rt>  pattern space </rt></ruby>，这是一个内存空间，其中包含来自输入流的当前行（删除了尾部的任何换行符）。填充模式空间后，sed 将执行你的指令。当命令执行完时，sed 将模式空间中的内容打印到输出流，默认是 **标准输出**，但是可以将输出重定向到文件，甚至使用 `--in-place=.bak` 选项重定向到同一文件。


然后，循环从下一个输入行再次开始。


为了在遍历文件时提供一点灵活性，sed 还提供了<ruby> 保留空间 <rt>  hold space </rt></ruby>（有时也称为 <ruby> 保留缓冲区 <rt>  hold buffer </rt></ruby>），即 sed 内存中为临时数据存储保留的空间。你可以将保留空间当作剪贴板，实际上，这正是本文所演示的内容：如何使用 sed 复制/剪切和粘贴。


首先，创建一个示例文本文件，其内容如下：



```
Line one
Line three
Line two

```

### 复制数据到保留空间


要将内容放置在 sed 的保留空间，使用 `h` 或 `H` 命令。小写的 `h` 告诉 sed 覆盖保留空间中的当前内容，而大写的 `H` 告诉 sed 将数据追加到保留空间中已经存在的内容之后。


单独使用，什么都看不到：



```
$ sed --quiet -e '/three/ h' example.txt
$

```

`--quiet`（缩写为 `-n`）选项禁止显示所有输出，但 sed 执行了我的搜索需求。在这种情况下，sed 选择包含字符串 `three` 的任何行，并将其复制到保留空间。我没有告诉 sed 打印任何东西，所以没有输出。


### 从保留空间复制数据


要了解保留空间，你可以从保留空间复制内容，然后使用 `g` 命令将其放入模式空间，观察会发生什么：



```
$ sed -n -e '/three/h' -e 'g;p' example.txt

Line three
Line three

```

第一个空白行是因为当 sed 第一次复制内容到模式空间时，保留空间为空。


接下来的两行包含 `Line three` 是因为这是从第二行开始的保留空间。


该命令使用两个唯一的脚本（`-e`）纯粹是为了帮助提高可读性和组织性。将步骤划分为单独的脚本可能会很有用，但是从技术上讲，以下命令与一个脚本语句一样有效：



```
$ sed -n -e '/three/h ; g ; p' example.txt

Line three
Line three

```

### 将数据追加到模式空间


`G` 命令会将一个换行符和保留空间的内容添加到模式空间。



```
$ sed -n -e '/three/h' -e 'G;p' example.txt
Line one

Line three
Line three
Line two
Line three

```

此输出的前两行同时包含模式空间（`Line one`）的内容和空的保留空间。接下来的两行与搜索文本（`three`）匹配，因此它既包含模式空间又包含保留空间。第三行的保留空间没有变化，因此在模式空间（`Line two`）的末尾是保留空间（仍然是 `Line three`）。


### 用 sed 剪切和粘贴


现在你知道了如何将字符串从模式空间转到保留空间并再次返回，你可以设计一个 sed 脚本来复制、删除，然后在文档中粘贴一行。例如，将示例文件的 `Line three` 挪至第三行，sed 可以解决这个问题：



```
$ sed -n -e '/three/ h' -e '/three/ d' \
-e '/two/ G;p' example.txt
Line one
Line two
Line three

```

* 第一个脚本找到包含字符串 `three` 的行，并将其从模式空间复制到保留空间，替换当前保留空间中的任何内容。
* 第二个脚本删除包含字符串 `three` 的任何行。这样就完成了与文字处理器或文本编辑器中的 *剪切* 动作等效的功能。
* 最后一个脚本找到包含字符串 `two` 的行，并将保留空间的内容\_追加\_到模式空间，然后打印模式空间。


任务完成。


### 使用 sed 编写脚本


再说一次，使用单独的脚本语句纯粹是为了视觉和心理上的简单。剪切和粘贴命令作为一个脚本同样有效：



```
$ sed -n -e '/three/ h ; /three/ d ; /two/ G ; p' example.txt
Line one
Line two
Line three

```

它甚至可以写在一个专门的脚本文件中：



```
#!/usr/bin/sed -nf

/three/h
/three/d
/two/ G
p

```

要运行该脚本，将其加入可执行权限，然后用示例文件尝试：



```
$ chmod +x myscript.sed
$ ./myscript.sed example.txt
Line one
Line two
Line three

```

当然，你需要解析的文本越可预测，则使用 sed 解决问题越容易。发明 sed 操作（例如复制和粘贴）的“配方”通常是不切实际的，因为触发操作的条件可能因文件而异。但是，你对 sed 命令的使用越熟练，就越容易根据需要解析的输入来设计复杂的动作。


重要的事情是识别不同的操作，了解 sed 何时移至下一行，并预测模式和保留空间包含的内容。


### 下载备忘单


sed 很复杂。虽然它只有十几个命令，但它灵活的语法和原生功能意味着它充满了无限的潜力。为了充分利用 sed，我曾经参考过一些巧妙的单行命令，但是直到我开始发明（有时是重新发明）自己的解决方案时，我才觉得自己真正开始学习 sed 了 。如果你正在寻找命令提示和语法方面的有用技巧，[下载我们的 sed 备忘单](https://opensource.com/downloads/sed-cheat-sheet)，然后开始一劳永逸地学习 sed！




---


via: <https://opensource.com/article/21/3/sed-cheat-sheet>


作者：[Seth Kenlon](https://opensource.com/users/seth) 选题：[lujun9972](https://github.com/lujun9972) 译者：[MjSeven](https://github.com/MjSeven) 校对：[wxy](https://github.com/wxy)


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


OK
Few Unix commands are as famous as sed, [grep](https://opensource.com/article/21/3/grep-cheat-sheet), and [awk](https://opensource.com/article/20/9/awk-ebook). They get grouped together often, possibly because they have strange names and powerful tools for parsing text. They also share some syntactical and logical similarities. And while they're all useful for parsing text, each has its specialties. This article examines the `sed`

command, which is a *stream editor*.

I've written before about [sed](https://opensource.com/article/20/12/sed), as well as its distant relative [ed](https://opensource.com/article/20/12/gnu-ed). To get comfortable with sed, it helps to have some familiarity with ed because that helps you get used to the idea of buffers. This article assumes that you're familiar with the very basics of sed, meaning you've at least run the classic `s/foo/bar/`

style find-and-replace command.

**[Download our free sed cheat sheet]**

## Installing sed


If you're using Linux, BSD, or macOS, you already have GNU or BSD sed installed. These are unique reimplementations of the original `sed`

command, and while they're similar, there are minor differences. This article has been tested on the Linux and NetBSD versions, so you can use whatever sed you find on your computer in this case, although for BSD sed you must use short options (`-n`

instead of `--quiet`

, for instance) only.

GNU sed is generally regarded to be the most feature-rich sed available, so you might want to try it whether or not you're running Linux. If you can't find GNU sed (often called gsed on non-Linux systems) in your ports tree, then you can [download its source code](http://www.gnu.org/software/sed/) from the GNU website. The nice thing about installing GNU sed is that you can use its extra functions but also constrain it to conform to the [POSIX](https://opensource.com/article/19/7/what-posix-richard-stallman-explains) specifications of sed, should you require portability.

MacOS users can find GNU sed on [MacPorts](https://opensource.com/article/20/11/macports) or [Homebrew](https://opensource.com/article/20/6/homebrew-mac).

On Windows, you can [install GNU sed](https://chocolatey.org/packages/sed) with [Chocolatey](https://opensource.com/article/20/3/chocolatey).

## Understanding pattern space and hold space

Sed works on exactly one line at a time. Because it has no visual display, it creates a *pattern space*, a space in memory containing the current line from the input stream (with any trailing newline character removed). Once you populate the pattern space, sed executes your instructions. When it reaches the end of the commands, sed prints the pattern space's contents to the output stream. The default output stream is **stdout**, but the output can be redirected to a file or even back into the same file using the `--in-place=.bak`

option.

Then the cycle begins again with the next input line.

To provide a little flexibility as you scrub through files with sed, sed also provides a *hold space* (sometimes also called a *hold buffer*), a space in sed's memory reserved for temporary data storage. You can think of hold space as a clipboard, and in fact, that's exactly what this article demonstrates: how to copy/cut and paste with sed.

First, create a sample text file with this text as its contents:

```
Line one
Line three
Line two
```


## Copying data to hold space

To place something in sed's hold space, use the `h`

or `H`

command. A lower-case `h`

tells sed to overwrite the current contents of hold space, while a capital `H`

tells it to append data to whatever's already in hold space.

Used on its own, there's not much to see:

```
$ sed --quiet -e '/three/ h' example.txt
$
```


The `--quiet`

(`-n `

for short) option suppresses all output but what sed has performed for my search requirements. In this case, sed selects any line containing the string `three`

, and copying it to hold space. I've not told sed to print anything, so no output is produced.

## Copying data from hold space

To get some insight into hold space, you can copy its contents from hold space and place it into pattern space with the `g`

command. Watch what happens:

```
$ sed -n -e '/three/h' -e 'g;p' example.txt
Line three
Line three
```


The first blank line prints because the hold space is empty when it's first copied into pattern space.

The next two lines contain `Line three`

because that's what's in hold space from line two onward.

This command uses two unique scripts (`-e`

) purely to help with readability and organization. It can be useful to divide steps into individual scripts, but technically this command works just as well as one script statement:

```
$ sed -n -e '/three/h ; g ; p' example.txt
Line three
Line three
```


## Appending data to pattern space

The `G`

command appends a newline character and the contents of the hold space to the pattern space.

```
$ sed -n -e '/three/h' -e 'G;p' example.txt
Line one
Line three
Line three
Line two
Line three
```


The first two lines of this output contain both the contents of the pattern space (`Line one`

) and the empty hold space. The next two lines match the search text (`three`

), so it contains both the pattern space and the hold space. The hold space doesn't change for the third pair of lines, so the pattern space (`Line two`

) prints with the hold space (still `Line three`

) trailing at the end.

## Doing cut and paste with sed

Now that you know how to juggle a string from pattern to hold space and back again, you can devise a sed script that copies, then deletes, and then pastes a line within a document. For example, the example file for this article has `Line three`

out of order. Sed can fix that:

```
$ sed -n -e '/three/ h' -e '/three/ d' \
-e '/two/ G;p' example.txt
Line one
Line two
Line three
```


- The first script finds a line containing the string
`three`

and copies it from pattern space to hold space, replacing anything currently in hold space. - The second script deletes any line containing the string
`three`

. This completes the equivalent of a*cut*action in a word processor or text editor. - The final script finds a line containing
`two`

and*appends*the contents of hold space to pattern space and then prints the pattern space.

Job done.

## Scripting with sed

Once again, the use of separate script statements is purely for visual and mental simplicity. The cut-and-paste command works as one script:

```
$ sed -n -e '/three/ h ; /three/ d ; /two/ G ; p' example.txt
Line one
Line two
Line three
```


It can even be written as a dedicated script file:

```
#!/usr/bin/sed -nf
/three/h
/three/d
/two/ G
p
```


To run the script, mark it executable and try it on your sample file:

```
$ chmod +x myscript.sed
$ ./myscript.sed example.txt
Line one
Line two
Line three
```


Of course, the more predictable the text you need to parse, the easier it is to solve your problem with sed. It's usually not practical to invent "recipes" for sed actions (such as a copy and paste) because the condition to trigger the action is probably different from file to file. However, the more fluent you become with sed's commands, the easier it is to devise complex actions based on the input you need to parse.

The important things are recognizing distinct actions, understanding when sed moves to the next line, and predicting what the pattern and hold space can be expected to contain.

## Download the cheat sheet

Sed is complex. It only has a dozen commands, yet its flexible syntax and raw power mean it's full of endless potential. I used to reference pages of clever one-liners in an attempt to get the most use out of sed, but it wasn't until I started inventing (and sometimes reinventing) my own solutions that I felt like I was starting to *actually* learn sed. If you're looking for gentle reminders of commands and helpful tips on syntax, [download our sed cheat sheet](https://opensource.com/downloads/sed-cheat-sheet), and start learning sed once and for all!

## Comments are closed.