古老的行编辑器:ed
本文将介绍行编辑器ed
。
什么是ed
ed
是Unix
系统最早的行编辑器之一,是一个面向行的文本编辑器,用于对文件进行增喊改查操作。后续熟知的vi
、awk
、sed
等都借鉴了ed
编辑器的设计,比如,vi
的底层是行编辑器ex
(ed
特征的扩展集)。
好在Gnu
项目将其移植到了Linux
中,我们才得以在Linux
中使用它,地址为: https://www.gnu.org/software/ed/。
当前文档使用的
ed
版本为:GNU ed 1.20
安装ed
目前最新的版本是1.20
版本
当前时间:2024年10月31日
下载ed
# wget https://ftp.gnu.org/gnu/ed/ed-1.20.tar.lz
解压
# lzip -d ed-1.20.tar.lz
# tar xf ed-1.20.tar
编译安装
# cd ed-1.20
# ./configure
# make
# make install
查看版本
# ed --version
若安装完成,会输出以下信息
GNU ed 1.20
Copyright (C) 1994 Andrew L. Moore.
Copyright (C) 2024 Antonio Diaz Diaz.
License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
ed的基本使用
启动ed编辑器
使用ed filename
,该命令会尝试打开filename
文件,若当该文件不存在时,则会报错filename: No such file or directory
,ed
则会进入到编辑模式,直到手动保存,该文件才会被创建,并且写入内容。
文件存在:
# ed filename_1
12
q
#
当文件存在的时候,使用ed
即可打开该文件,并且输出字符数,输入q退出。
文件不存在:
# ls -lhta filename_2
ls: cannot access filename_2: No such file or directory
#
# ed filename_2
filename_2: No such file or directory
a
hello filename_2
.
w
17
q
# cat filename_2
hello filename_2
#
当文件不存在的时候,使用ed
尝试打开该文件的时候,会报错No such file or directory
,但是还是会进入到编辑模式,此时若输入a
命令,接着输入需要追加的行hello filename_2
,输入.
进行结束输入,命令w
则进行保存,保存完成后,会输出字符数,最后输入q
进行退出ed
编辑器。
数据打印和遍历
进入ed
编辑器打开文件后,可以通过如下命令打印和定位行信息。
数据准备
# echo -e '123\n456\n789' >> filename_1
#
# cat filename_1
hello world
123
456
789
#
使用p
显示当前的行:
# ed filename_1
24
p
789
使用ed
默认打开文件后,会进入到最后一行。使用p
命令可以显示当前行。
使用,p
打印所有行:
# ed filename_1
24
,p
hello world
123
456
789
使用ed
默认打开文件后,使用,p
会打印所有行。
若想打印固定的行的话,可以使用{startN},{endN}p
命令,这才是,p
的完整写法,如,打印2到4行,则命令如下:
# ed filename_1
24
2,4p
123
456
789
使用=
打印当前文件的行号
# ed filename_1
24
=
4
除此之外,还能使用n
来打印所在行的行号和内容
# ed filename_1
24
n
4 789
若想输出固定行,和p
命令类似,如,打印2到4行的内容,包括行号,则命令如下:
# ed filename_1
24
2,4n
2 123
3 456
4 789
行定位
ed
打开文件后,默认会定位到最后一行,如下命令,可以快速进行行定位。
准备数据:
# echo -e "a\nb\nc\nd\ne\nf" > filename_1
在ed
中,输入1
可以定位到第一行,$
则定位到最后一行。
# ed filename_1
12
1
a
$
f
不仅如此,还能基于当前行进行快速定位,比如定位到当前行的后2行。
# ed filename_1
12
1
a
+2
c
定位到当前行的前2行。
# ed filename_1
12
$
f
-2
d
追加文本
在ed
中,有2个命令,分别是a
和i
,其含义如下:
a
:在当前行后追加行i
:在当前行前插入行
使用a
进行追加行
# ed filename_1
24
a
a append to data
.
w
41
q
#
在ed
中,使用a
命令后会进入到插入模式,可以输入多行的内容,输入完成后,输入.
进行结束输入,w
会保存内容到磁盘,q
则退出ed
编辑器。
查看文件内容
# cat filename_1
hello world
123
456
789
a append to data
#
使用i
插入行
# ed filename_1
41
1
hello world
n
1 hello world
i
hello insert data
ooooooo
.
w
67
q
#
上述命令中,在ed
打开filename_1
后,使用1
先切到到第1行,并且使用n
输出当前行的行号和内容,随后输入i
指令,插入了2行内容,输入.
进行结束输入,随后保存到磁盘,接着退出。
查看文件
# cat filename_1
hello insert data
ooooooo
hello world
123
456
789
a append to data
#
需要插入的内容,已经被插入到最前面了。
如果在追加内容中,恰好需要在单行输入.
,该.
将作为字符,而非结束标志符,应该在该.
后再追加一个空格,例如.
,实际操作如下:
# > filename_1
#
# ed filename_1
0
i
insert into data
.
123456
.
w
27
q
请注意,在insert...
和123456
之间的.
,是.
+ 空格,否则会被当成是结束符。
使用cat -A
来查询一下:
# cat -A filename_1
insert into data$
. $
123456$
#
删除行
在ed
中,使用d
可以进行删除行操作,首先进行数据准备:
# echo -e "a\nb\nc\nd\ne\nf" > filename_1
# cat filename_1
a
b
c
d
e
f
#
使用d
可以删除当前行:
# ed filename_1
12
d
,p
a
b
c
d
e
进入ed
后,默认会定位到最后一行,使用d
指令,将删除最后一行,即f
被删除了。
不仅如此,还能指定行进行删除,比如2到4行进行删除:
# ed filename_1
10
2,4d
,p
a
e
进入ed
后,使用2,4d
指令,将删除2到4行,即b
、c
被删除了。
如果想删除全部行,则直接执行,d
即可删除所有行:
# ed filename_1
4
,d
文件的退出
使用q
指令会尝试退出ed
编辑器,当内存数据没有写入到磁盘的时候,会报错?
。
# ed filename_1
0
a
123
.
q
?
此时若想退出ed
编辑器,可以使用Q
指令进行强制退出,内存的数据将会丢弃,不会写入到磁盘中。
# cat filename_1
# ed filename_1
0
a
123
.
q
?
Q
# cat filename_1
#
若想保存后退出ed
编辑器,可以使用w
先进行写入到磁盘,而后使用q
进行退出。
# ed filename_1
0
a
123
.
w
4
q
# cat filename_1
123
#
ed的高级操作
数据准备
在开始之前,需要准备一份数据
# cat >> test.txt << EOF
name age sex
Alice 28 F
Bob 32 M
Charlie 25 M
Daisy 29 F
Ethan 30 M
Fiona 27 M
George 31 M
Hannah 26 F
Isaac 33 M
Julia 24 F
EOF
#
查看数据
# cat test.txt
name age sex
Alice 28 F
Bob 32 M
Charlie 25 M
Daisy 29 F
Ethan 30 M
Fiona 27 M
George 31 M
Hannah 26 F
Isaac 33 M
Julia 24 F
#
查看数据基本信息
# wc test.txt
11 33 200 test.txt
#
其中test.txt
的信息为:
- 11行
- 33个单词
- 200个字符
ed查询行数据
准备工作
使用ed
跟上文件名,即可打开文件。
该操作是将文件的内容放到内存缓冲区中,当编辑完成后,需要手动保存,此时才会将内存中的数据写入磁盘中。
# ed test.txt
200
默认使用ed
打开文件后,会输出文件字符数,并且将位置定位到最后一行。
简单查询
此时使用p
会打印当前行的内容,即最后一行。
# ed test.txt
200
p
Julia 24 F
若想查询所有的内容,可,p
即可。
,p
name age sex
Alice 28 F
Bob 32 M
Charlie 25 M
Daisy 29 F
Ethan 30 M
Fiona 27 M
George 31 M
Hannah 26 F
Isaac 33 M
Julia 24 F
复杂搜索
若想查询符合规范的行,比如sex
是M
的行。
g/M/p
Bob 32 M
Charlie 25 M
Ethan 30 M
Fiona 27 M
George 31 M
Isaac 33 M
其中g
表示全局、M
表示搜索关键字为M
,p
是打印匹配行,每个指令由/
分割开来,若不包含g
则默认只匹配一行。
/M/p
Bob 32 M
若想更为精确的匹配,如 1-8行中出现M
的行信息。
1,8g/M/p
Bob 32 M
Charlie 25 M
Ethan 30 M
Fiona 27 M
George 31 M
利用正则表达式搜索
除此之外,ed
还支持正则表达式,比如查询name
以e
结尾的行信息。
g/.*e\s/p
name age sex
Alice 28 F
Charlie 25 M
George 31 M
其正则表达式.*e\s
的意思是匹配以e
紧接着空格的行。
ed 编辑行数据
数据准备
要编辑行内容,首先要先将文件加载到内存缓冲区中,即使用ed
打开文件。
# ed test.txt
200
进行简单的替换
现在将第一行的a
替换为A
1
name age sex
s/a/A/
1
nAme age sex
首先,需要切换到第一行,然后使用 s/a/A/
将小写的 a
替换为大写的 A
。不过,查看后发现该命令只修改了第一个出现的 a
,而后续的 a
并未替换。
这是因为在默认情况下,ed
只会修改首次匹配到的内容。若想替换整行中的所有匹配项,需要在命令后添加参数 g
,表示全局替换。
接下来,将第一行中的 e
替换为 E
,并对所有匹配项进行替换。
1
nAme age sex
s/e/E/g
1
nAmE agE sEx
从上面的结果可以看出,替换已成功完成。
进行全局替换
如果想要将文本中所有的 e
替换为 E
,则需要使用以下参数。
g/.*/s/e/E/g
,p
nAmE agE sEx
AlicE 28 F
Bob 32 M
CharliE 25 M
Daisy 29 F
Ethan 30 M
Fiona 27 M
GEorgE 31 M
Hannah 26 F
Isaac 33 M
Julia 24 F
g/.*/s/e/E/g
的含义如下:
- 第一个
g
:表示全局操作。 .*
:表示匹配所有行。s/e/E/
:表示将e
替换为E
。- 最后一个
g
:表示全局替换。
进行特定行区间数据替换
若只想修改特定行区间的内容,可以更改 .*
的参数值,例如:
,p
nAmE agE sEx
AlicE 28 F
Bob 32 M
CharliE 25 M
Daisy 29 F
Ethan 30 M
Fiona 27 M
GEorgE 31 M
Hannah 26 F
Isaac 33 M
Julia 24 F
2,$s/E/e/g
,p
nAmE agE sEx
Alice 28 F
Bob 32 M
Charlie 25 M
Daisy 29 F
ethan 30 M
Fiona 27 M
George 31 M
Hannah 26 F
Isaac 33 M
Julia 24 F
2,$s/E/e/g
的含义是:在第二行到最后一行的范围内匹配包含 E
的内容,并将其替换为 e
。
在ed
中执行shell
命令
在ed
中可以执行简单的命令,比如: 获取一下当前的服务器时间。
# ed
! date
Mon Nov 4 14:25:23 CST 2024
!
注意,ed
只能识别最简单的命令,如有特殊字符,比如date +"%F %T"
则不行,因为%
是特殊字符,用于引用文件和行,%
正确的用法为:
# ed filename_1
12
! ls %
ls filename_1
filename_1
!
而如果直接使用date +"%F %T"
,会达不到预期效果:
# ed filename_1
12
! date +"%F %T"
date +"filename_1F filename_1T"
filename_1F filename_1T
!
好在可以将该命令写入外部文件中,在ed
中进行调用即可:
首先,需要先准备好脚本
# echo 'date +"%F %T"' >> getDate.sh
# sh getDate.sh
2024-11-04 14:36:34
#
而后在ed
中调用该脚本即可
# ed
! sh getDate.sh
2024-11-04 14:37:30
!
不仅如此,ed
还支持将执行的结果插入到当前文本中,例如:
# ed
r ! sh getDate.sh
20
,p
2024-11-04 14:40:38
只需要r !
加上执行的命令,即可将命令执行的结果插入到当前文本中。
ed 脚本化
可以将ed
的编辑命令放在独立的文件中,并且将他们作为ed
行编辑器的输入,这样的话ed
就具备了脚本化的能力。
例如: 将一些列的ed
语句放入到ed.script
的文件中,可以利用下面的命令,对文件执行该ed
脚本:
ed filename < ed.script
可以来尝试一下:
首先,来编写ed.script
(可以任意命名该文件)
# cat ed.script
0,r ! date
$,a
the end.
ed url site: https://www.gnu.org/software/ed
.
g/.*/s/a/A/g
g/.*/s/c/C/g
w
q
#
解析一下每个语句的含义:
0,r ! date
:在首行插入date
命令执行的结果。$,a
:在尾行追加2行字符,第一行为:the end.
,第二行为:ed url site: https://www.gnu.org/software/ed
,第三行的.
是a
命令的结束符。g/.*/s/a/A/g
:进行全文全局替换,将a
替换为A
。g/.*/s/c/C/g
:进行全文全局替换,将c
替换为C
。w
:保存。q
:退出。
接着,使用ed filename < ed.script
的形式来执行该脚本。
首先,先查看filename_1
的内容。
# cat filename_1
a
b
c
d
e
f
#
接着,便对该文件执行ed.script
命令。
# ed filename_1 < ed.script
12
29
95
#
最后再次查看filename_1
文件。
# cat filename_1
Mon Nov 4 15:14:21 CST 2024
A
b
C
d
e
f
the end.
ed url site: https://www.gnu.org/softwAre/ed
#
总结
ed
是Uinx
下的上古行编辑器,在目前的主流Linux
版本中,都没有了它的身影,但是它影响了sed
、grep
、vi
等一众软件,甚至于在上述软件使用中都能看到ed
的身影。
如果你正在学习sed
、grep
、vi
等,不妨花几分钟了解一下ed
这个“老前辈”。
古老的行编辑器:ed
https://wangli2025.github.io/2024/11/04/The-oldest-line-editor-ed.html
本站均为原创文章,采用 CC BY-NC-ND 4.0 协议。转载请注明出处,不得用于商业用途。