如果你看过 Rob Pike 的 twitter 主页, 也许会注意到他在简介只写了一句话: Ed Is the Standard Text Editor。
可见Ed作为一个文本编辑器,应该是有其特别之处。 本文来谈谈它特别在哪儿。
Ed 是什么
ed
是一个Unix系统上的行编辑器。 说到编辑器,可能很多人首先想到的是vi
。其实Ed是它的“祖师爷“。
ed
堪称软件行业的活化石,它诞生于1969年,与 Unix 同龄,比C语言正式面世还早9年。 它的作者是 Unix 发明人 Ken Thompson。
事实上, Ken Thompson 就是为了方便 Unix 操作系统的研发和测试才先开发了3个关键工具: 汇编器,编辑器(即 ed
) 及 Shell。 这么说来, 早期的Unix也就是在这个编辑器里诞生的。
在诞生几年以后,Dennis M. Ritchie(是的, 就是 “K&R C” 里面的那个 “R”) 开发了一个新版ed
, 被Doug McIlroy称为“终级ed”。 ed
的各方面功能直接影响了后继者 ex, 而ex
直接影响甚至定义了vi
。
当然 ed
也不是一夜之间冒出来的, 它从更早的文本编辑器 qed 那里继承和借鉴了很多。
主要特点
ed
有3个主要特点。
一,简洁
ed
极其简洁,几乎没有任何视觉反馈。我推测这与 Ken Thompson 的设计哲学有一定关系, 毕竟整个 Unix 哲学就建立在简单之上。当然还有另外一个与时代背景相关的原因:那时的控制台还是电传打字机,调制解调器很慢,内存也很宝贵。尽量减少视觉反馈以节约资源也就可以理解了。
若在使用过程中遇到错误情况(例如输入了不支持命令), 它只返回一个 "?" , 完全不给其它提示。 也不报告文件名、行号等基本信息。 最变态的是,在早期版本中若用户没保存就想退出, 它居然都不提示确认。 所以它也被 Peter H. Salus 称为“史上最仇视用户的编辑器”。
二,省资源
前面提到的“变态级简洁”,就是因为当时资源有限。 因此, ed
在使用时占用资源非常少。不论是内存还是硬盘使用都远低于其它编辑器。举例来说, 现代ed
一般占用硬盘空间约 50k, 与之对应的vi
基本上不低于2M。
三,免安装
由于是“单一Unix规范” 的一部分,所以任何Unix及其派生系统都内置了ed
命令。 这有利于我们在系统其它功能不可用的时候用它作一些应急文本编辑。再加上占用资源少的特点,使得它出现在大到高端服务器、小到树莓派的各种设备上。 连iPad 上的 ssh 软件blink都在其shell环境里提供了ed
命令。
快速上手
了解了背景信息, 接下来看看它的具体功能和使用方法。
两种运行模式
ed
运行的时候会在两种模式之间切换。一种是命令模式,另一种是输入模式。
在命令模式下,它会从标准输入读取命令,并对缓存区中的内容进行相应操作。 典型的命令如 ,s/old/new/g
, 其含义是把所有old
替换成new
。 如前面所说, vi
发源于 ed
, vi
用户看到这个命令应该感到非常熟悉。 注意,搜索是支持正则表达式的。
在命令模式下, 键入任意一个输入命令(例如,命令i
用于插入), ed
便转入输入模式。 这时任何输入会直接写入目标缓冲区。 要想结束输入模式, 需要新起一行并键入一个英文句点, 再回车后ed
便从输入模式转回成命令模式。
其运行模式转换过程如下图所示:
示例
在了解了ed
的工作模式以后, 我们来看一个广为流传的官方示例: 首先启动ed
, 然后陆续输入命令,控制台显示信息如下。注意以下信息有部分是手工键入的,部分是软件输出来。 下面有详细解释:
a
ed is the standard Unix text editor.
This is line number two.
.
2i
.
,l
ed is the standard Unix text editor.$
$
This is line number two.$
3s/two/three/
,l
ed is the standard Unix text editor.$
$
This is line number three.$
w text
65
q
以上内容部分由用户键入,部分由软件输出。 下面来解释一下:
第1行, 键入命令
a
,含义是开始追加(append),回车后软件从命令模式转入输入模式。第2-3行,输入两行文本内容
第4行,结束输入模式,转入命令模式
第5行,键入命令
2i
, 含义是在缓冲区中第二行入插入(insert)新内容第6行,输入一个空行
第7行,结束输入
第8行,链入命令
,l
, 其含义是打印出缓冲区中所有内容。第9-11行便是打印内容。 注意每行结尾处显式输出的
$
代表一行结束, 目的是让用户看到行尾可能出现的空格第12行,把在缓冲区中第三行中所有
two
替换成three
第13-16行, 再次打印缓存区内容, 以检查编辑结果
第17行,把缓冲区内容保存到名为
text
的文件中第18行,65代表写入文件的字节数
第19行,退出
可见掌握了它的运行规律以后,是可以用它比较高效地完成文本编辑的。
命令格式
典型的ed
命令格式如下:
[address[,address]]command[parameters]
地址格式
命令前面两个可选的address
代表行地址。 当省略地址时, 每个命令会把操作作用到对应的“默认地址”上。 每个命令的默认地址会有很不同。
由于本文并不打算代替官方手册, 下面仅列出常用的几种地址形式加以说明:
.
当前行$
最后一行n
第n行-
前一行-n
前n行同理
+
,+n
分别代表后一行,后n行,
全部行,等同于1,$
/re/
下一个匹配正则表达式re
的行
常用命令
ed
历史悠久,版本众多,此处仅列出最早、最核心的命令。 要想了解每个平台上的详细情况请参考平台命令手册。
a
追加c
修改,即删除当前行,并进入输入模式,以输入内容替换原始内容d
删除i
插入l
列出指定行地址内容q
退出。 如果有缓冲区中有未保存的内容, 会有提示r file
读取file内容,将其从当前位置追加到缓冲区中s/re/replacement/
用replacement
替换re
匹配的第一行s/re/replacement/g
同上,只是替换全部行s/re/replacement/n
同上,只是替换第n行
命令实例
下面列出几个使用命令的实例, 以便让大家对 ed
的使用有一个更直观的认识:
ed foo.txt
: 打开 foo.txt , 并将文件内容读取缓冲区中l
: 列出当前行内容,l
: 列出缓存区中所有内容8,$l
: 列出第8行至最后一行的所有内容8c
修改第8行s/foo/bar/g
搜索缓存区中全部行,将所有 foo 改成 bar2,4d
删除第2至4行
注意事项
由于ed
太过简洁, 有时在使用过程中都不知自己处于什么模式。 这时 -p
参数,或命令模式下的 P
命令 就能帮上忙了。 此参数允许用户指定命令提示符。 有提示符存在的时候, 说明是命令模式。 例如
$ed -p:
:
?
:q
$
总结
把ed
与 vi
对比之后就不难发现, 虽然在视觉反馈方面有区别, 在但在命令定义和操作模式上, vi
基本上沿袭了 ed
这个“古代”软件。
由于可见, ed
虽然古老,但其开创的交互模式即使在50年后的今天仍被广泛使用。 也许这就是 "Ed Is the Standard Text Editor" 被一直提及的原因。
不过,虽然其影响被继承, 但ed
本身现在的确很少被用到。 对于交互式编辑, 多数人会选 vi
, emacs
等编辑器。 若要在命令行中快速解析与处理文本, 其流式版本 sed
(stream editor) 是更好的选择。 后续文章我们可以聊聊它的继承者们。
p.s. ED在英文中是阳痿的缩写,所以围绕这个软件也产生了一些经典段子 ^-^