Sed

sed（意为流编辑器，源自英语“stream editor”的缩写）是一个使用简单紧凑的编程语言来解析和转换文本Unix实用程序。 sed由贝尔实验室的李·E·麥克馬洪于1973年至1974年开发， 并且现在大多数操作系统都可以使用。 sed基于交互式编辑器ed（“editor”，1971）和早期qed（“quick editor”，1965-66）的脚本功能。sed是最早支持正则表达式的工具之一，至今仍然用于文本处理，特别是用于替换命令。用于纯文本字符串操作和“流编辑”的常用工具还有AWK和Perl 。 sed是为命令行处理数据文件而构建的早期Unix命令之一，首次出现在Version 7 Unix中 。它很自然地演变成为流行的grep命令的后继。 最初的动机与grep（g/re/p）的替换类似，因此称为“g/re/s”。 考虑到这样的话还会出现针对每个命令的专用程序，例如g/re/d，李·E·麥克馬洪编写了一个通用的面向行的流编辑器，该编辑器后来成为了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将其替换到输出里。 除了替换之外，使用大约25个sed命令可以进行其他形式的简单处理。例如，下面使用d 命令删除空行或只包含空格的行： sed '/^ *$/d' inputFileName 本例使用了下列正则表达式元字符（sed支持所有正则表达式）： 脱字符（ ^ ）匹配行首。 美元符号（ $ ）匹配行尾。 星号（ * ）匹配前一个字符零次或多次出现。 可以有很复杂的sed结构，让sed用作一种简单但高度专业化的编程语言。例如，可以通过使用标签（冒号后跟字符串）和分支指令b来管理控制流程。指令b后跟有效的标签名称，将把处理流程移动到该标签后面的块。 在Unix下，sed通常用作管道中的过滤器： $ generateData | sed 's/x/y/g' 也就是说，诸如“generateData”之类的程序生成数据，然后用sed把x替换成y。例如： $ echo xyz xyz | sed 's/x/y/g' yyz yyz 将几个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 # convert input text stream to "Hello, world!" s/.*/Hello, world!/ q 这个“Hello, world!”脚本位于文件（如script.txt）中，并使用sed -f script.txt inputFileName调用，其中“inputFileName”是输入文本文件。脚本将“inputFileName”第1行更改为“Hello, world!”然后退出，在sed退出之前打印结果。第1行后的任何输入行都不会被读取，也不会被打印。唯一的输出是“Hello, world!”。 这个例子强调了sed的许多关键特性： sed是独一无二的。没有其他“Hello, world!”例子与之相似。 典型的sed程序相当简短。 sed脚本可以有注释（以#符号开头的行）。 s（替换）命令是最重要的sed命令。 sed允许使用q（退出）等命令进行简单编程。 sed使用正则表达式，例如.* （任何字符的零个或多个）。 下面是各种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（通常仅在一行上工作）会在某一行的后一行以一个空格打头的情况下删除换行符。 请考虑以下文本： This is my dog, whose name is Frank. This is my fish, whose name is George. This is my goat, whose name is Adam. 下面的sed脚本会将上面的文本转换为以下文本。请注意，该脚本仅影响以空格开头的输入行： This is my dog, whose name is Frank. This is my fish, whose name is George. This is my goat, whose name is Adam. 使用的脚本是： N s/\n / / P D 这段脚本应按如下理解： （N）将下一行添加到模式空间； （s/\n / /）查找一个换行符后跟一个空格，替换为一个空格； （P）打印模式空间的顶行； （D）从模式空间中删除顶行并再次运行脚本。 这可以通过分号在一行中表示出来: sed 'N; s/\n / /; P; D' inputFileName 虽然sed具有简单性和局限性，但对于大量用途而言，它的功能已经足够强大。对于更复杂的处理，可以使用更强大的语言，如AWK或Perl或者PowerShell。虽然使用保持缓冲区理论上可以进行任意复杂的转换，但如果转换行的方式比正则表达式提取和模板替换更复杂，则使用一般会使用上面提到的更强大的语言。 相反，对于更简单的操作，grep （打印匹配模式的行），head（打印文件的第一部分），tail（打印文件的最后部分）和tr（翻译或删除字符）等专门的Unix实用程序通常更可取。对于设计用于执行的特定任务，此类专用实用程序通常比较一般的解决方案（如sed）更简单、清晰和快速。 ed/sed命令和语法继续用于派生程序，例如文本编辑器vi和vim。sam/ssam与ed/sed类似，其中sam是Plan 9编辑器，ssam是它的流接口，其功能类似于sed。 在命令行使用中，表达式周围的引号不是必需的，只有在shell不会将表达式解释为单个字（标记）时才需要。由于脚本s/x/y/g没有歧义，所以generateData | sed s/x/y/g工作正常。然而，为了清楚起见，通常是要写引号的，特别是对于有空格的时候（例如，'s/x x/y y/'）。大多数情况下，使用单引号是为了避免shell将$解释为shell变量。使用双引号，如"s/$1/$2/g"，是为了让shell替换命令行参数或其他shell变量。 The sed FAQ, Section 2.1. [2013-05-21]. （原始内容存档于2018-06-27）.  The sed FAQ, Section 2.2. [2013-05-21]. （原始内容存档于2018-06-27）.  McIlroy, M. D. A Research Unix reader: annotated excerpts from the Programmer's Manual, 1971–1986 (PDF) (技术报告). CSTR. Bell Labs. 1987 [2018-11-10]. 139. （原始内容存档 (PDF)于2019-11-30）.  On the Early History and Impact of Unix. [2018-11-10]. （原始内容存档于2017-09-07）. A while later a demand arose for another special-purpose program, gres, for substitution: g/re/s. Lee McMahon undertook to write it, and soon foresaw that there would be no end to the family: g/re/d, g/re/a, etc. As his concept developed it became sed…  Implementation of a Turing Machine as Sed Script. [2018-11-10]. （原始内容存档于2018-02-20）.  Turing.sed. [2018-11-10]. （原始内容存档于2018-01-16）.  The $SED Home - gamez. [2009-04-20]. （原始内容存档于2006-02-08）.  bolknote/SedChess. GitHub. [2018-11-10]. （原始内容存档于2018-12-02）.  Sedtris, a Tetris game written for sed. [2018-11-10]. （原始内容存档于2018-12-02）.  贝尔实验室的第八版（约1985年）Unix sed（1）手册页（页面存档备份，存于互联网档案馆） GNU sed（1）手册页 Dale Dougherty & Arnold Robbins. sed & awk 2nd. O'Reilly. March 1997 [2018-11-10]. ISBN 1-56592-225-5. （原始内容存档于2018-11-02）.  Arnold Robbins. sed and awk Pocket Reference 2nd. O'Reilly. June 2002 [2018-11-10]. ISBN 0-596-00352-8. （原始内容存档于2018-11-11）.  Peter Patsis. UNIX AWK and SED Programmer's Interactive Workbook (UNIX Interactive Workbook). Prentice Hall. December 1998 [2018-11-10]. ISBN 0-13-082675-8. （原始内容存档于2020-04-09）.  Daniel Goldman. Definitive Guide to sed. EHDP Press. February 2013 [2018-11-10]. ISBN 978-1-939824-00-4. （原始内容存档于2018-01-29）.  Sourceforge.net（页面存档备份，存于互联网档案馆） ，sed FAQ（2003年3月） 維基教科書中的相關電子教程：en:sed sed – 命令与工具（Commands & Utilities）参考，单一UNIX®规范第7期，由國際開放標準組織发布 Sed - An Introduction and Tutorial（页面存档备份，存于互联网档案馆）, by Bruce Barnett SED -- A Non-interactive Text Editor (1974)（页面存档备份，存于互联网档案馆）, by Lee E. McMahon 31+ Examples For Sed Linux Command In Text Manipulation（页面存档备份，存于互联网档案馆）, by Mokhtar Ebrahim Sed教學（页面存档备份，存于互联网档案馆） Major sources for sed scripts, files, usage Roger Chang's SED and Shell Scripts (2012)（页面存档备份，存于互联网档案馆） Top 'sed' commands – Usage examples Sed command examples in Unix & Linux（页面存档备份，存于互联网档案馆） GNU sed主页（包括GNU sed手册） sed the Stream Editor（2004）（页面存档备份，存于互联网档案馆） （Eric Pement） sed-users Yahoo讨论组（页面存档备份，存于互联网档案馆） Unix实用程序列表 AWK tr PowerShell