Sed

历史

sed是为命令行处理数据文件而构建的早期Unix命令之一，首次出现在Version 7 Unix中 。它很自然地演变成为流行的grep命令的后继。 最初的动机与grep（g/re/p）的替换类似，因此称为“g/re/s”。 考虑到这样的话还会出现针对每个命令的专用程序，例如g/re/d，McMahon编写了一个通用的面向行的流编辑器，该编辑器后来成为了sed。 sed的语法，特别是把/用于模式匹配，把s///用于替换，起源于sed的前身ed（当时ed很常用） 而且正则表达式语法影响了其他一些语言，特别是ECMAScript和Perl。后来，更强大的语言AWK问世，这些工具相互补充，让通过shell脚本完成强大的文本处理成为可能。sed和AWK常被认为Perl的祖先和灵感来源，并且影响了Perl的语法和语义，尤其影响了匹配和替换运算符。
GNU sed添加了一些新功能，包括文件的就地编辑。Super-sed 是sed的扩展版本，包含与Perl兼容的正则表达式。sed的另一变体minised ，最初埃里克·雷蒙把4.1BSD sed通过逆向工程写成，当前由René Rebe维护。在GNU计划基于新的GNU正则表达式库编写了新版本的sed之前，GNU计划一直使用minised。当前minised包含一些BSD sed的扩展，但不像GNU sed那样功能丰富。它的优点是速度快，占用的内存少。它用于嵌入式系统，是Minix提供的sed版本。

工作模式

sed是一个面向行的文本处理实用程序：它从输入流或文件中逐行读取文本到一个称为模式空间 的内部缓冲区。每读一行开始一个循环  。对于模式空间，sed会应用sed脚本 指定的一个或多个操作。sed实现了一种编程语言，其中包含大约25个指定文本操作的命令  。对于每个输入行，在运行脚本之后，sed通常输出模式空间（由脚本修改的行），然后从下一行再次开始循环。其他脚本结束行为可通过sed选项和脚本命令获得，例如d删除模式空间，q退出，N立即将下一行添加到模式空间，等等。因此，sed脚本对应于循环体，循环体遍历流的行，其中循环本身和循环变量（当前行号）是隐式的并由sed维护。
可以在命令行上指定sed脚本（ -e选项），也可以从单独的文件中读取（ -f选项）。sed脚本中的命令可以采用行号或正则表达式的作为地址  。该地址确定决定命令何时运行。例如，2d将仅在第二个输入行上运行d（删除）命令（打印除第二个输入行之外的所有行），而/^ /d将删除以空格开头的所有行。一些单独的特殊缓冲区，即保持空间，可以由几个sed命令使用，用于在循环之间保持和累积文本。sed的命令语言只有两个变量（“保持空间”和“模式空间”）和类似GOTO的分支功能；然而，这种语言是图灵完全的， 用深奥sed脚本甚至写得出推箱子、打砖块、国际象棋和俄罗斯方块等游戏。 
为输入流的每一行执行一次主循环，在输入的每一行上计算sed脚本。sed脚本的每一行都是模式-动作对，指示着要匹配的模式和要执行的操作，可以将其重新组合为条件语句。因为主循环、工作变量（模式空间和保持空间）、输入和输出流以及默认操作（复制行到模式空间、打印模式空间）是隐式的，所以可以编写简洁的单行程序。例如，以下sed程序：
10q
将打印输入的前10行，然后停止。

替换命令

下面的示例显示了sed用于替换的典型（也是最常见的）用法。这种用法确实是sed的最初动机：
sed 's/regexp/replacement/g' inputFileName > outputFileName
在某些版本的sed中，表达式的前面必须加上-e，以表示后面跟着一个表达式。s表示替换，而g表示全局，这意味着行中的所有匹配项都将被替换。要搜索的正则表达式（即pattern）放在第一个分隔符号（此处为斜杠）之后，而要替换成的字符串跟在第二个分隔符号后面。斜杠（/）是传统的符号，起源于ed中的“搜索”字符，但其实在pattern和替换文本中都未出现的任何其他符号都可以用作分隔符号，使其可读性更强；这有助于避免“倾斜牙签综合征”。
替换命令源自ed中的搜索-替换，实现了简单的解析和模板化。regexp提供模式匹配和通过子表达式保存文本的功能，而replacement可以是纯文本，也可以是包含“完全匹配”&，或第n 个子表达式（从\1到\9）这种特殊转义序列的格式字符串。例如， sed -r "s/(cat|dog)s?/\1s/g"用“cat”或“dog"替换所有出现的“cats”或“dogs”，而不复制现有的“s”：在正则表达式中，(cat|dog)是第一个（也是唯一）保存的子表达式，格式字符串中的\1将其替换到输出里。

sed用作过滤器

在Unix下，sed通常用作管道中的过滤器：
generateData | sed 's/x/y/g'
也就是说，诸如“generateData”之类的程序生成数据，然后用sed把x替换成y。例如：
$ echo xyz xyz | sed 's/x/y/g'yyz yyz

基于文件的sed脚本

将几个sed命令（每行一个命令）放入脚本文件（例如subst.sed）中然后使用-f选项从文件中运行命令（例如s/x/y/g）通常很有用：
sed -f subst.sed inputFileName > outputFileName
可以在脚本文件中放置任意数量的命令，使用脚本文件也可以避免shell转义或替换的问题。
这样的脚本文件可以直接从命令行执行，方法是在其前面加上一个包含sed命令的"shebang行"，并为该文件分配可执行权限。例如，可以使用以下内容创建文件subst.sed：
!/bin/sed -f
s/x/y/g

然后，当前用户可以使用chmod命令使文件可执行：
chmod u+x subst.sed
然后可以直接从命令行执行该文件：
subst.sed inputFileName > outputFileName

就地编辑

GNU sed中引入的-i选项允许就地编辑文件（实际上，在后台创建了一个临时输出文件，然后将原始文件替换为临时文件）。例如：
sed -i 's/abc/def/' fileName

其他简单的例子

下面是各种sed脚本；可以把它们作为参数传递给sed，或者放入一个单独的文件并通过-f执行或通过使脚本本身可执行来执行。
要把文件中某个单词（例如IRC密码）替换为“REDACTED”，并保存结果：
sed -i s/yourpassword/REDACTED/ ./status.freenode.log
要删除包含“yourword”一词的所有行（ 地址 为“/yourword/”）：
/yourword/ d
要删除所有“yourword”这个词：
s/yourword//g
要同时从文件中删除两个单词：
s/firstword//g
s/secondword//g
为了在一行表示前面的示例，比如在命令行输入时，可以通过分号连接两个命令：
sed "s/firstword//g; s/secondword//g" inputFileName

限制和替代方案

虽然sed具有简单性和局限性，但对于大量用途而言，它的功能已经足够强大。对于更复杂的处理，可以使用更强大的语言，如AWK或Perl 。虽然使用保持缓冲区理论上可以进行任意复杂的转换，但如果转换行的方式比正则表达式提取和模板替换更复杂，则使用一般会使用上面提到的更强大的语言。
相反，对于更简单的操作，grep （打印匹配模式的行），head（打印文件的第一部分），tail（打印文件的最后部分）和tr（翻译或删除字符）等专门的Unix实用程序通常更可取。对于设计用于执行的特定任务，此类专用实用程序通常比较一般的解决方案（如sed）更简单、清晰和快速。
ed/sed命令和语法继续用于派生程序，例如文本编辑器vi和vim。sam/ssam与ed/sed类似，其中sam是Plan 9编辑器，ssam是它的流接口，其功能类似于sed。