人們如何使用ed?


90

ed是標準的Unix編輯器,並且存在於所有POSIX認證的系統上(儘管默認情況下未在Debian,FWIW中安裝它)。

這是一個行編輯器(意思是,您一次看不到所有文本。您查詢行號並將其退回,但它出現在vi [1]之前,您可以在其中使用hjkl向上導航並在屏幕上)。

如何使用?我發現很難相信人們對代碼的記憶足夠好,以至於他們記得在第20行[2]上工作時第5行發生了什麼?

人們是否在紙上寫代碼,然後鍵入(有點像打孔卡時代),編輯紙,然後通過ed修改代碼?

[1]。小點一點,ed誕生了ex,而vi是ex的"可視模式",而ex的遺產在現代vim / neovim中仍然可見(當您輸入:COMMAND,如:w時,vi運行ex命令),因此ed遺產至今仍然存在。

[2]。節目在70年代還不太長。只是沒有足夠的RAM給他們。但是,即使短短的20行程序仍然太複雜,以致無法逐行完全保留在我的大腦中。

24

You have to remember that 'ed', originally, was as often as not being used on a teletype, not a video terminal, so the line-oriented paradigm made sense. Even then, knowing enough 'ed' to get around files was valuable when, for example, you were using a really dumb terminal (I recall an IBM 3101 that for reasons I forget I was forced to use occasionally that was just easier to use 'ed' on), or when you'd borked up your tty params to the point you couldn't get the full screen editors to work.


110

It's a line editor (meaning, you can't see all the text at a time. You query line numbers and it spits it back, but it came before vi, where you can use hjkl to navigate up and down the screen).

How was it used? I find it hard to believe that people memorized their code well enough that they could remember what was going on in line 5 when working on line 20?

Using a line-based editor isn't that hard.

  • For one, yes, real programmers (as we all were back then) do remember their lines. (*1)
  • Next, when on a writing terminal, one lists the working on section once, so all you need to do to take a look is pull the paper.
  • On a dump terminal one could just issue a list (print) command for the actual range, or ,p for all, as often as needed.

Did people write code on a paper and then type it in (sort of like in the punch-card days), editing the paper and then modifying code through ed?

Yes and no. Before writing a program one sits down and draws a rough structure. Something I'd assume everyone still does today. How else do you get a first glimpse if your idea for a structure is valid? After that, ed (or similar editors on mainframes) is all a programmer needs. A program grows in your head; the screen is just to dump the result, isn't it?

Also, assembling/compiling did usually produce a listing which could be used to go thru on paper (if printed out), add remarks and new lines before hacking them in again. And no, you didn't compile every few seconds and remove just the top warning/error. One worked thru the whole error list before compiling again.

Programs weren't too long in the 70s. There just wasn't enough RAM for them. But even a short 20 line program is still too complicated to fully keep in my brain, line by line.

How are you able to understand your own program if you can't visualize it in the first place? (I'm serious here: I couldn't, and I don't know how it would work otherwise.)

And again, in all seriousness, I worked with line editors over years and on programs with more than 200 lines. In fact, ed already has more features than are absolutely necessary, as edlin has everything you really need to program.


*1 - I can't stop myself from adding a 'little' story about how real programmers remember their code here:


From Grandpa's Vault:

How Real Programmers Remember Code

In the mid '80s (~1985) I was working mostly for a somewhat large, /370 based, mainframe application. At that time the software consisted of about 1.1 million lines of hand written assembly (~1.2M including secondary programs, Only statements, excluding empty lines, etc.). It had its own database engine (*2), screen handling (more than 800 different screen layouts), own editor (*3), own networking stack, own runtime and so on. A typical installation had, at this point about 100-300 full-time users.

The project had been around since the early 1970s. We worked on a policy of no-wrappers, which means only modules were used which we did understand and if necessary were modified to fit the system, and redoing the whole code base every 4-6 years, to avoid ageing code. After all, in a real world application requirements change all the time and so does code. It's a matter of style to avoid rucksack solutions. Nonetheless, 'lint' accumulates over the years and a start over was done every 4-6 years.

At that time we also had scored a new contract with a very promising customer(*4), so a lot of changing and adaptations were needed to incorporate the functionality of two other large scale systems and put them out of business. So a perfect time for a 100% redesign. We were a core team of 4 programmers. Unlike previous times we didn't have a relaxed schedule, but had to implement everything until an already agreed roll-out date, set less than 3 years away. Not cool. We still had (wanted and needed) to go ahead with a total redesign, so management (*5) did assign 14 additional men and we were moved into something like a designer and lead programmer role.

Of course, these were all 'super specialists' and way better than anything we were ... the usual game. And as so often they came up with the same questions, why not use a high level language(*6), a standard DBS and so on. The usual crap. Seriously, with an application of that size, writing such components is just a minor add on. Eventually needing less code than using a standard interface requires - not to mention being faster because being tailored exactly to our needs.

Anyway, let's go for the story. One of these 'specialists', lets call him Mr. W., claimed that no one can oversee such a large codebase, not even partially. Heck, no one can even remember all code written by himself in 5 or more years. Ha! That was a claim that I couldn't let stand uncontested, so one word yielded the next. Bottom line: we agreed for a bet, one beer, that I will be able (he said not able) to identify source name when presented a 10 line snippet, from random programs I did within the existing codebase. We agreed on 10 examples. Date was set the next morning.

Morning came, I didn't prepare nothing, but he came up with a stack of paper and a case of beer. I guess his intention was to show how much I didn't gain by presenting every fail with a bottle. Also, he was so generous as to make the snippets a whole page each. I didn't really need that. I named not only each routine he handed me, but also which module it belonged to, what's the purpose, some workings, why variables are named the way they are, some caller or what was to be found on the pages before or after. Further, I also named the original programer (*7), as he inserted a few pages from programs I didn't write and identified a piece of code that was no longer used, told why and what has replaced it - he pulled it form a very old version :))

The whole case of beer, bottle by bottle, changed sides :))

The same time Mr. W. became more and more quiet. Needless to say that there was no further argument about readability of code or the ability to handle a large code base. Sure, there was still the database fight, but that's a different story.


*2 - Up to 10.000 user transactions per hour with even more DB access per transaction on a 1 MIPS machine with 1.25 MiB RAM - that's mainframe to you :))

*3 A full screen editor on block based terminals. Think of it like ed on steroids. There was no scrolling or alike, but you could edit any of the 20 displayed lines locally before sending that 'page' back to the host to be sorted into the source again (everything was based on sets of libraries, which again worked as a versioning system).

*4 - About a dozen planned installations. For mainframe ERP software, that's like hitting the jackpot, maybe comparable to selling several million copies of a game or such.

*5 - Management also changed at that time, lucky us :(

*6 - Until today, no one could explain to me how Buffer := Record. is supposed to be more readable than MVC BUFFER,RECORD - no, we are not talking C, only real languages were up for decision :)

*7 - Programmers have a 'handwriting' no matter what language is used. There is a way conditions are formed, a likeliness for the selection of field names and so on. When working for some time with others, one clearly knows to 'hear' this like a voice speaking.


30

Before the advent of interactive terminals (and version control programs), most programmers were used to keeping their source code on 80-column punched cards. On the first mainframe that I worked on (a Honeywell system), work-flow was typically as follows:

  • Initial source code would be entered on 80-column coding pads, and these would be transferred to punched cards by the punch-room typists. This would be a lot quicker than typing it yourself, even if you had access to a card punch. The punch-room girls (yes, they were all women) would also do paper tape, but this was universally loathed, and was only used for systems that had no card reader.

  • Any edits to your source code would either be done via the punch room, or by yourself if you had a card punch. This might either be a manual card punch (which were readily available), or a punch/interpreter similar to those in the punch room.

  • When you got your program working, you would then store your code in a source code library. Note that this was not a version control system. It simply allowed you to save your working code on disk (and then archive the card deck in a secure cabinet). You then had the option of archiving the entire library on magnetic tape once you had a fully working program.

  • All of the compilers and assemblers would accept standard line editor commands, so that you could modify the code in the source libraries on the fly without having to update them.

  • Once you got your modifications working, you could then update the source code libraries using the standard line editor, and re-archive the library.

  • Edit decks could then either be merged with the original card decks or stored as incremental updates, in case you lost the source code libraries (usually due to disk failure).

The system was cumbersome, but it worked, and the transition to line-oriented terminals was seamless. If you think that this way of working would drive you mad, bear in mind that you would be lucky to get two compiles in a normal working day. Even then, your jobs would be run by operators; you were not allowed to run the jobs yourself since computer time was an expensive commodity. The more knowledgeable operators would correct simple typing errors for you if your compile failed (and they had time to do so).

enter image description here

Manual 80-column card punch

enter image description here

IBM 029 80-column card punch/interpreter

enter image description here

Honeywell Series 60 Level 62 small business computer (circa 1975)

An 80-column card reader can be seen on the far right. This was capable of reading 2,000 cards per minute. An 80-column card punch/interpreter can be seen next to it. I cannot remember its speed, but it was probably around 100 cards per minute. This demo-centre machine lacked 9-track magnetic tape drives. Otherwise, it was fairly similar to our development machine.


66

The reason you can't keep a 20 line program in your head is because you don't have to any more. Same reason you probably don't know any phone numbers.

But back in the day, we certainly did do this. I have written thousands of lines of code and text and documentation using line editors (not ed). At 110, 300, 1200 and 2400 baud. The 2400 baud terminals were nice, but 1200 was completely usable. 300 and 110, not so much - functional, but not preferred. On a single screen which was only 80x24. I never cared for the printing terminals. They were OK, but the glass ttys were so much better.

I used to write English papers on the school mainframe. We had something akin to RUNOFF or troff. You think a line editor is bad, you should try using an actual typewriter some day. The line editor is much better.

My English teacher was kind enough to accept composition papers printed on the back of greenbar.

Many of the habits from line editors carry over to editors like vi and emacs. And old habits die hard. In a line editor you don't simply page or scroll through your code. Rather, you search. It still drives me nuts to watch someone in a code file with hundreds of lines scroll and "aim" for a section of code when they could have simply searched for the function name to get there instantly. At least use the page down key, man!

What I would do, and I can't cite specifics, as I've forgotten the editor commands, and don't know ed), but simply I'd search and then print the next 10 lines.

As you get adept, you quickly learn to string commands together. Search for a line and delete it. Go to a line, make a change, etc. Almost every command I made ended with the "print the line" command so I could see what I did. The editor I used allowed editing commands on the command line so I was able to make changes without actually "entering" the editor.

You could use sed for that today.

sed -i -e '10s/old/new/' file.txt

Go to the 10th line, change the first "old" to "new", and overwrite the file (file.txt).

Today, we are very fortunate in terms of computing resources and powerful code editors and word processors. And we get quite jaded. It is quite difficult to "go back". A single screen, no scroll back, no command history, a line editor, using Ctrl+S and Ctrl+Q to stop and restart output. If any of this sounds terrible to you, it was leaps and bounds above using cards. Cards were terrible.


4

Back in the late 1980s, I worked with multiple infant Unix mutants whose terminal support was an afterthought. If I had to tweak a file, I would telnet in and use a line editor like ex or ed to make the fix. Jumping to a particular line number or searching for a distinct pattern was necessary to navigate large files. Wholesale changes were usually done by ftp, local edit using a screen editor, and ftp back. I do remember struggling with a file that was too large for my screen editor; I may have used a line editor to complete the edits or merely partition the file.

IIRC Real Programmers used

% cat - >foo

not ed to write code.


19

ed was the standard Unix editor, and is present on all POSIX certified systems (though it's not installed by default in Debian, FWIW).

Indeed it was and when I first went to University in 1984, they taught me how to use it. Then they said "there's also vi, type man vi". vi by the way was actually little more than some extensions on another line editor called ex in those days.

By the way, if you were working on a paper teletype (we weren't, we had glass terminals that emulated the VT52), you had to use a line editor.

It's a line editor (meaning, you can't see all the text at a time. You query line numbers and it spits it back

Not true. Each command was prefixed by an address which could be a line number, a range of line numbers or a pattern (if my memory serves correctly). So you could do 1,$p which would print the whole file. On a glass VDU printing the whole file in this way was typically a pointless waste of time because all but the last 25 lines would have scrolled off the top of the screen and there was no scrolling back to find them like you get with modern terminal emulations.

How was it used? I find it hard to believe that people memorized their code well enough that they could remember what was going on in line 5 when working on line 20

Well the situation wasn't much better with full screen editors because you could only see a window of 24 lines (with vi, the bottom line was the command line). The way I used to work was to print off a hard copy of the code periodically and have it beside me on the desk when writing or debugging code. When I changed something, I'd mark up the paper listing, not necessarily with the change but with a mark to remind me that that section was now out of date.

Did people write code on a paper and then type it in

No. At least I didn't. Well, when I got my first job we did that, but that is because our company office didn't have a computer of the right type for the client we were working for. We'd do our debugging and changes on paper using paper listings and then drive to the customer's site to type in the changes.

Programs weren't too long in the 70s

Is that what you think?

Edit

In case it is not clear that the above is a flat denial of the assertion that there were no long programs in the 70's, it's fair to say there were long programs. For example, compilers and operating systems tended to be very large. In fact, in the 70's most operating systems were written in assembler meaning the Unix kernel as originally written in assembler would have more lines of source code than the C version (assuming the C version didn't have too many extra features).

Of course, individual source code files could be of arbitrary length and still can be. So, in a 100,000 line program you might have 50 C code files, each 2,000 lines long on average and you still would today.


4

I started to write my thesis using ed and I got very good at searching for unique words I could remember using. I was on a vdu so I could print out a range of lines to review what I had written or run the scribe compile job and send it to the line printers.

Then we got to upgrade to vi and latex and life became much easier.


3

On the line editor I used (SOS on a DEC-10, ca. 1984), the lines surrounding the line you were working on were visible, and you could scroll back and forth as necessary. It could be disconcerting to see lines appear in reverse order as you scrolled back up through the file, but it was something you got used to relatively quickly. Not quite as speedy as using a mouse and scroll wheel, but not crippling either.

Of course, once we upgraded to a VAX and got screen-based editors (EDT, LSE, etc.), we never looked back.


10

As a university undergrad in the 1980s we were not allowed to use vi as an editor, only ed, because of the limited resources of the VAX 750 shared by the thousands of undergrads on campus.

It wasn't a problem because you learned how to use your tools. For example, you want to list the lines 1 through 10, you would just type 1,10p (or 1,10n for a numbered listing, or 1,10l to show non-printing character, or...). You had no need to memorize you code, you could just see it on the screen. For larger chunks, you'd just send the whole file to the line printer.

Try using gdb from the command line. It's pretty much the same experience even today.


5

My first several years of college included a variety of line editors on different systems. Many thousands of lines of code as I wrote 3D image generation and analysis systems. Oddly, the programming devices were old 80x24 text terminals and our high-end graphic output device was a ComRecorder... a $300,000 machine that in fact was nothing but sealed black box containing a tiny color monitor with a Nikon camera pointed at it... (turn on a pixel, cycle the shutter, repeat). Took 26 hours of compute time to generate a 3000x2000 pixel image, then wait 2 days to get the film developed.

One of the line editors of the day was called xedit -- I still call what I do everyday the "xedit-compile-damn" loop.

On keeping code in your head... this was something you could actually do partially because you wrote everything. There were practically no libraries of code you could browse and integrate. The few that existed often needed a complete rewrite to work with your OS or compiler. My story...

I was working on a new Dell 386-based machine in '87 running a flavor of Unix, writing the database admin UI for a barcode scanning system (the back office app for a grocery store). The video card failed in the computer and I continued to edit code, modify the database design, and compile systems for 6 days without ever seeing a single character on the screen until a new video card arrived. This was likely 30-50,000 lines of code spread through a substantial folder structure. That was the mind-muscle-memory you developed from never taking your fingers off the keyboard. The machine was slow, so you were used to typing into a command buffer and being 3-5 commands ahead of what was actually running. It was normal then, but a skill that could never be developed after the mouse became a primary input tool. I certainly couldn't do it today.


5

Beyond what has already mentioned in other answers, keep in mind that sometimes you know exactly what you need to change and where, especially during the typical edit-compile-test cycle typical of classical software development. Think for example of the output most C compilers give when they hit a compilation error, you get a line number and an excerpt of the line where the error was. In such a case, it's not all that difficult for someone with even a very basic understanding of ed to make the necessary change.


5

As others have said, around 1975-1978 we would write a program by hand on coding pads and send it to the punch room to be punched onto 80-column cards. It would then be taken down to the computer room for the first attempt at compilation; if you were lucky you got the output back 2 hours later. Compilation would always produce a complete line printer listing of the program, complete with line numbers (we used lorry-loads of line printer paper). The compiler error messages would also refer to line numbers, so you could then see where the errors were.

There were then several ways you might apply the corrections (in my case I was using (a) in 1972, (b) in 1975, and (c) in 1978):

(a) punch replacement cards yourself for the incorrect lines, and insert them into the card deck.

(b) punch a set of editing commands into a new deck of cards, and submit a batch job to apply these edits to the disk-based file containing the source code

(c) wait until an interactive terminal became available - initially a teletype, subsequently a VDU that essentially emulated a teletype - and enter the editing commands interactively at the terminal. (Usual practice was to start at the end of the file and work towards the front, so that the line numbers on the line printer listing remained valid as long as possible). Then submit a batch compile job, and wait two hours to get the listing back, generally with a new set of error messages.

By about 1979 we were starting to see editors developed to take advantage of VDU capabilities (vi being a not-particularly-good example); but we carried on using line-oriented editing because once you had memorised all the commands available, it was actually faster.


9

Blind people still program this way today. Those screenreaders they use are only 120characters wide and 3 lines high. This is for a very expensive model (like the price of a car).


3

If you are used to a modern editor then it is likely that using ed seems impossible but this applies to many modern items. How did people cope before they existed? You need to try to imagine that computers were new exciting things. They could do things that were previously unimaginable. ed didn't seem hard because we never dreamed of modern editors. If you wanted to program then you learned ed or some similarly limited editor.

In some ways, programs might actually have been bigger in those days, especially Cobol ones, as modular techniques were not so well supported or known. Thousands of lines was not uncommon. We did not memorise whole programs, well at least I didn't, but nonetheless we could usually find our way around successfully.

I have programmed with even more restricted editors. I used to own a Psion Organiser II and I programmed it on the device itself. At the time, I travelled a lot on business and I often wrote programs to pass the time. The display was 2 lines of 16 characters so you typically could not even see a complete line of your program at once. An example of a program that I wrote was a jet lag avoidance clock. I would input the take off time and time zone and the landing time and time zone. It would then run the clock fast or slow depending on whether I was going east or west. So, no sudden time change. A larger program was a costs log for my car, petrol, service, etc, and even depreciation.

Psion Organiser (Wikipedia)


6

Something not mentioned in other answers here here is that pretty much everyone learning computer programming on microcomputers through the mid-80s used line editing by default. The most common programming language was BASIC, and the most common "editor" was the line-oriented editing system provided as part of the BASIC implementation. You'd use the LIST command with line numbers to see some part of your current program, and retype lines by typing the line number followed by the new code. If you were moderately lucky, you could move your cursor up the screen to a line printed by that LIST command, edit it, and hit ENTER to have it replace that line.

Even when moving to other languages, assembly language being the most common after BASIC, line editing was the general rule. Apple's EDASM and Atari's Assembler Editor cartridge both used line-oriented editors.

So for someone coming from this background (as I did), the general use of ed was no big deal; it was more or less the same as what we'd been doing before. It was just a bit nicer because it had some extra features that weren't always present in microcomputer systems, at least when working in BASIC:

  • You could easily insert new lines, with line numbering being completely automatic. That is, 2i followed by a line of text and . (end input) would make the newly inserted line number 2, and what was line 2 became line 3.
  • Line numbers became "metadata," rather than part of the line itself, as it had been in BASIC.
  • We had the concept of a "current line."
  • We had commands for making specific edits to part of the current line, and we could look at the result and do further edits based on that. (s/foo/baz/p, examine result, try s/baz/bar/p.)
  • We had better commands for moving to a new current line, especially via searching (/foo() to jump to the function definition).

This turns out to be not much different from how an effective Vim user works nowadays anyway, except that you'd manually "print" or "number" some lines on to the screen before entering various editing commands to change them. A typical bit of editing might be:

/^int foo(          Set current line to the function defintion.
                    (The line is printed so you can see it's correct.)
.,.+15n             Print first 15 lines of function with line numbers.
                    (Let's say that the first line printed was 70.)
70s/)/, y)/         Add another parameter to the function
83a                 Append after line 73 (in this example, the last
                    line of the parameter declarations).
int y               Declare type of new parameter
.                   End of input
88i                 Insert new code for new parameter before line 88,
                    which was 87 before inserting the above line

And so on. So just as with modern editors you still had the bit of code you were working on displayed on the screen (not the whole file), you edited based on what was on the screen, and you moved your "viewport" around as you worked on different parts the file. The commands were usually slightly more awkward (.,.+20p instead of Ctrl-F to show the next "page") but not unduly so.

ex was a rather more sophisticated line editor (basically, vi without full screen mode) and offered an easier way of making edits within a line if you were using a "glass TTY," i.e., a screen-based terminal that didn't have an addressible cursor. Called "open mode," it was basically a one-line visual editor that used backspace, carriage return and reprinting of characters to move the cursor around so you could use the standard visual left/right by character and word etc. commands to move back and forth within the line. Moving up or down would simply start a new line on the screen showing the line above or below that you'd moved to.


3

I haven't used 'ed' seriously, but I've used several line-oriented editors: the Eldon 2 'amender' (EE KDF9), the George3 editor (ICL 1900), SOS (TOPS-10, on DECsystem-10). They all are similar editors, though with one significant difference: could you revisit 'previous' lines in the file or not?

The George3 editor/Eldon 2 amender were, if memory serves, single-pass sequential editors; SOS held a 'page' at a time, so you could revisit lines on the same page.

The navigation commands available in all of these were basically 'go to line N' or 'go to the next line containing X'. Then to edit, you got facilities for retyping the entire line, replacing substrings, and various other operations. If you needed to go backwards, this was accomplished by writing out the rest of the file and starting again from the top (depending on editor, there might be a command to do that, otherwise you did it 'manually').

For 'big changes' you might well list the program source on a lineprinter and mark it up, not necessarily with exact changes, but whatever you needed to know what you're doing. For minor stuff, well, you wrote the code, you knew what it looked like. And last week's listing, not entirely accurate now since the code had changed, would be a memory-jogger.

A certain amount of work was done away from the teletype, but this had as much to do with the fact that there were generally more teletype users than teletypes, so you wanted to maximize your efficiency when you got some machine time.

Even TECO, a character-oriented editor rather than a line editor, required similar skills to keep track of whether you are, though it did have the benefit that you could navigate backwards, at least up to the last page boundary/yank command.

So, yeah, in response to the 'how' part of the question: we learned how to work with the tools we'd got, or to come up with incremental improvements within the technological limits of the systems we worked on. Because whatever limits there were on interactive editing, it was much better than working offline with papertape or punchcards.

As regards to programmers remembering their code, or not, I once was fairly sure I could intimately remember up to 3K PDP-11 words of MACRO-11 assembler. This was fine since I was writing kernel code that had to be structured as 'processes' of no more than 4K words (there were several such processes making up the 'program', of course). I can't really remember, but I think that 3K words is about a couple of inches of lineprinter paper.


3

It's perhaps worth noting that line editors were originally developed for printing teletypes, before addressable CRT terminals were widely available. They did require a certain amount of holding your program file in memory, although you could print out sections of the code. In practice, this was a cognitive skill that programmers using them tended to learn.

Uphill both ways etc. Now get off my lawn.


5

Cool thread! I thought of something I could contribute, an ed session captured just now, which as I came up with it, reminded me how not bad ed is:

$ ed hello.c
hello.c: No such file or directory
a
#include <stdio.h>
int main() {
  printf("hello, world!\n");
  return 0;
}
.
w
75
q
$ cc -o hello hello.c
$ ./hello
hello, world!
$ 

okay, so that could have been done more easily with cat > hello.c, but now let's edit the file:

$ ed hello.c
75
1
#include <stdio.h>

int main() {

  printf("hello, world!\n");
d
i
  printf("hello again, world!\n");
.
w
81
q
$ !cc
cc -o hello hello.c
$ ./hello
hello again, world!

that's pretty cool, IMO. Doable over a hard tty with no cursor movement.


3

There is a book Ed Mastery by Michael W Lucas, that might be a good source if you are interested.

I guess, in the beginning it was supposed to be a bit of a joke, but it became useful for connecting the dots and I basically read it in an afternoon and actually used some of the knowledge/ approaches later on professionally.