Advanced Editing with vi

The preceding hour focused on the basics of inserting and deleting text and moving around within a file. This hour adds a critical capability: searching and replacing text within a file.

Task 11.1: Searching Within a File

With the addition of two more capabilities, you'll be ready to face down any vi expert, demonstrating your skill and knowledge of the editor, and, much more importantly, you will be able to really fly through files, moving immediately to the information you desire.


The two new capabilities are for finding specific words or phrases in a file and for moving to specific lines in a file. Similar to searching for patterns in more and page, the /pattern command searches forward in the file for a specified pattern, and ?pattern searches backward for the specified pattern. To repeat the preceding search, use the n command to tell vi to search again, in the same direction, for the next instance of the same pattern.

You can move easily to any specific line in a file by using the G, or go-to-line, command. If you type a number before you type G, the cursor will move to that line in the file. If you type G without a line number, the cursor will zip you to the last line of the file (by default).

  1. Start vi again with the big.output file:

    								leungtc  ttyrV   Dec  1 18:27   (magenta)
    tuyinhwa ttyrX   Dec  3 22:38   (expert)
    hollenst ttyrZ   Dec  3 22:14   (dov)
    brandt   ttyrb   Nov 28 23:03   (age)
    holmes   ttyrj   Dec  3 21:59   (age)
    yuxi     ttyrn   Dec  1 14:19   (pc)
    frodo    ttyro   Dec  3 22:01   (mentor)
    labeck   ttyrt   Dec  3 22:02   (dov)
    chenlx2  ttyru   Dec  3 21:53   (mentor)
    leungtc  ttys0   Nov 28 15:11   (gold)
    chinese  ttys2   Dec  3 22:53   (excalibur)
    cdemmert ttys5   Dec  3 23:00   (mentor)
    yuenca   ttys6   Dec  3 23:00   (mentor)
    janitor  ttys7   Dec  3 18:18   (age)
    mathisbp ttys8   Dec  3 23:17   (dov)
    janitor  ttys9   Dec  3 18:18   (age)
    cs541    ttysC   Dec  2 15:16   (solaria)
    yansong  ttysL   Dec  1 14:44   (math)
    mdps     ttysO   Nov 30 19:39   (localhost)
    md       ttysU   Dec  2 08:45   (muller)
    jac      ttysa   Dec  3 18:18   (localhost)
    eichsted ttysb   Dec  3 23:21   (pc1)
    sweett   ttysc   Dec  3 22:40   (dov)
    "big.output" 40 lines, 1659 characters
    

    Remember that I used :q! to quit earlier, so my changes were not retained.

    To move to the last line of the file, I type G once, and I see this:

    cdemmert ttysk   Dec  3 22:37   (xsun)
    jrlee    ttysn   Dec  3 22:53   (mac1)
    fitzgejs ttyso   Dec  3 23:18   (dov)
    doerrhb  ttysp   Dec  3 23:20   (dov)
    cdemmert ttysq   Dec  3 23:00   (xsun)
    frazierw ttysr   Dec  3 23:01   (dov)
    buckeye  ttyss   Dec  3 23:20   (mac2)
    mtaylor  ttyst   Dec  3 23:22   (dov)
    look     ttysu   Dec  3 23:12   (age)
    janitor  ttysw   Dec  3 18:29   (age)
    ajones   ttysx   Dec  3 23:23   (rassilon)
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    

    To move to the third line of the file, I type 3 followed by G:

    leungtc  ttyrV   Dec  1 18:27   (magenta)
    tuyinhwa ttyrX   Dec  3 22:38   (expert)
    hollenst ttyrZ   Dec  3 22:14   (dov)
    brandt   ttyrb   Nov 28 23:03   (age)
    holmes   ttyrj   Dec  3 21:59   (age)
    yuxi     ttyrn   Dec  1 14:19   (pc)
    frodo    ttyro   Dec  3 22:01   (mentor)
    labeck   ttyrt   Dec  3 22:02   (dov)
    chenlx2  ttyru   Dec  3 21:53   (mentor)
    leungtc  ttys0   Nov 28 15:11   (gold)
    chinese  ttys2   Dec  3 22:53   (excalibur)
    cdemmert ttys5   Dec  3 23:00   (mentor)
    yuenca   ttys6   Dec  3 23:00   (mentor)
    janitor  ttys7   Dec  3 18:18   (age)
    mathisbp ttys8   Dec  3 23:17   (dov)
    janitor  ttys9   Dec  3 18:18   (age)
    cs541    ttysC   Dec  2 15:16   (solaria)
    yansong  ttysL   Dec  1 14:44   (math)
    mdps     ttysO   Nov 30 19:39   (localhost)
    md       ttysU   Dec  2 08:45   (muller)
    jac      ttysa   Dec  3 18:18   (localhost)
    eichsted ttysb   Dec  3 23:21   (pc1)
    sweett   ttysc   Dec  3 22:40   (dov)
    

    Notice that the cursor is on the third line of the file.

  2. Now it's time to search. From my previous travels in this file, I know that the very last line is for the account ajones, but instead of using G to move there directly, I can search for the specified pattern by using the / search command.

    Typing / immediately moves the cursor to the bottom of the screen:

    md       ttysU   Dec  2 08:45   (mueller)
    jac      ttysa   Dec  3 18:18   (localhost)
    eichsted ttysb   Dec  3 23:21   (pc1)
    sweett   ttysc   Dec  3 22:40   (dov)
    /_
    

    Now I can type in the pattern ajones:

    md       ttysU   Dec  2 08:45   (mueller)
    jac      ttysa   Dec  3 18:18   (localhost)
    eichsted ttysb   Dec  3 23:21   (pc1)
    sweett   ttysc   Dec  3 22:40   (dov)
    /ajones_
    							

    When I press Return, vi spins through the file and moves me to the first line it finds that contains the specified pattern:

    cdemmert ttysk   Dec  3 22:37   (xsun)
    jrlee    ttysn   Dec  3 22:53   (mac1)
    fitzgejs ttyso   Dec  3 23:18   (dov)
    doerrhb  ttysp   Dec  3 23:20   (dov)
    cdemmert ttysq   Dec  3 23:00   (xsun)
    frazierw ttysr   Dec  3 23:01   (dov)
    buckeye  ttyss   Dec  3 23:20   (mac2)
    mtaylor  ttyst   Dec  3 23:22   (dov)
    look     ttysu   Dec  3 23:12   (age)
    janitor  ttysw   Dec  3 18:29   (age)
    ajones   ttysx   Dec  3 23:23   (rassilon)
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    
  3. If I type n to search for this pattern again, a slash appears at the bottom line to show that vi understood my request. But the cursor stays exactly where it is, which indicates that this is the only occurrence of the pattern in this file.

  4. Looking at this file, I noticed that the account janitor has all sorts of sessions running. To search backward for occurrences of the account, I can use the ? command:

    ~
    ~
    ?janitor_
    							

    The first search moves the cursor up one line, which leaves the screen looking almost the same:

    cdemmert ttysk   Dec  3 22:37   (xsun)
    jrlee    ttysn   Dec  3 22:53   (mac1)
    fitzgejs ttyso   Dec  3 23:18   (dov)
    doerrhb  ttysp   Dec  3 23:20   (dov)
    cdemmert ttysq   Dec  3 23:00   (xsun)
    frazierw ttysr   Dec  3 23:01   (dov)
    buckeye  ttyss   Dec  3 23:20   (mac2)
    mtaylor  ttyst   Dec  3 23:22   (dov)
    look     ttysu   Dec  3 23:12   (age)
    janitor  ttysw   Dec  3 18:29   (age)
    ajones   ttysx   Dec  3 23:23   (rassilon)
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ?janitor
    

    Here's where the n, or next search, can come in handy. If I type n this time, and there is another occurrence of the pattern in the file, vi moves me directly to the match:

    yuxi     ttyrn   Dec  1 14:19   (pc)
    frodo    ttyro   Dec  3 22:01   (mentor)
    labeck   ttyrt   Dec  3 22:02   (dov)
    chenlx2  ttyru   Dec  3 21:53   (mentor)
    leungtc  ttys0   Nov 28 15:11   (gold)
    chinese  ttys2   Dec  3 22:53   (excalibur)
    cdemmert ttys5   Dec  3 23:00   (mentor)
    yuenca   ttys6   Dec  3 23:00   (mentor)
    janitor  ttys7   Dec  3 18:18   (age)
    mathisbp ttys8   Dec  3 23:17   (dov)
    janitor  ttys9   Dec  3 18:18   (age)
    cs541    ttysC   Dec  2 15:16   (solaria)
    yansong  ttysL   Dec  1 14:44   (math)
    mdps     ttysO   Nov 30 19:39   (localhost)
    md       ttysU   Dec  2 08:45   (muller)
    jac      ttysa   Dec  3 18:18   (localhost)
    eichsted ttysb   Dec  3 23:21   (pc1)
    sweett   ttysc   Dec  3 22:40   (dov)
    wellman  ttysd   Dec  3 23:01   (dov)
    tuttleno ttyse   Dec  3 23:03   (indyvax)
    wu       ttysf   Dec  3 23:10   (term01)
    daurismj ttysg   Dec  3 23:10   (dov)
    cs414    ttysh   Dec  3 23:12   (xds)
    

    When you're done, quit vi by using :q.

There are not dozens, but hundreds of commands in vi. Rather than overwhelm you with all of them, even in a table, I have opted instead to work with the most basic and important commands. By the time you're done with this hour, your knowledge of vi commands will be substantial, and you will be able to use the editor with little difficulty. The next hour will expand your knowledge with more shortcuts and efficiency commands.


This task focused on searching for patterns, which is a common requirement and helpful feature of any editor. In addition, you learned how to move to the top of the file (1G) and to the bottom of the file (G), as well as anywhere in between.

Task 11.2: The Colon Commands in vi

Without too much explanation, you have learned a couple of colon commands, commands that have a colon as the first character. The colon immediately zooms the cursor to the bottom of the screen for further input. These commands are actually a subset of quite a large range of commands, all part of the ex editor on which vi is based.


The colon commands that are most helpful are as listed here:

Command Function
:e filename Stop editing the current file, and edit the specified file.
:n Stop editing the current file, and edit the next file specified on the command line.
:q Quit the editor.
:q! Quit regardless of whether any changes have occurred.
:r filename Include the contents of the specified file at this position in the file that is currently being edited.
:w Save the file to disk.
:w filename Save the file to disk with the specified filename.

  1. Start vi again, this time specifying more than one file on the command line; vi quickly indicates that you want to edit more than one file:

    % vi buckaroo big.output
    2 files to edit.
    

    Then it clears the screen and shows you the first file:

    								I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    "buckaroo" 9 lines, 276 characters
    

    Using :w results in this:

    ~
    ~
    ~
    "buckaroo" 9 lines, 276 characters
    
  2. Instead, try writing to a different file, using :w newfile:

    ~
    ~
    :w newfile_
    							

    When you press Return, you see this:

    ~
    ~
    "newfile" [New file] 9 lines, 276 characters
    
  3. Now pay attention to where the cursor is in the file. The :r, or read-file, command always includes the contents of the file below the current line. Just before I press Return, then, here's what my screen looks like:

    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    :r newfile_
    							

    Pressing Return yields this:

    								I found myself stealing a peek at my own watch and overheard
    General Catbird's
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    

    This can be a helpful way to include files within one another, or to build a file that contains lots of other files.

  4. Now that I've garbled the file, I want to save it to a new file, buckaroo.confused:

    ~
    ~
    :w buckaroo.confused_
    							

    When I press Return, I see this:

    ~
    ~
    "buckaroo.confused" [New file] 17 lines, 546 characters
    

Older UNIX systems have a 14-character filename limit. If yours does, you will see buckaroo.confu as the saved filename.


  1. Now it's time to move to the second file in the list of files given to vi at startup. To do this, I use the :n, or next-file, command:

    ~
    ~
    :n_
    							

    Pressing Return results in the next file being brought into the editor to replace the first:

    								leungtc  ttyrV   Dec  1 18:27   (magenta)
    tuyinhwa ttyrX   Dec  3 22:38   (expert)
    hollenst ttyrZ   Dec  3 22:14   (dov)
    brandt   ttyrb   Nov 28 23:03   (age)
    holmes   ttyrj   Dec  3 21:59   (age)
    yuxi     ttyrn   Dec  1 14:19   (pc)
    frodo    ttyro   Dec  3 22:01   (mentor)
    labeck   ttyrt   Dec  3 22:02   (dov)
    chenlx2  ttyru   Dec  3 21:53   (mentor)
    leungtc  ttys0   Nov 28 15:11   (gold)
    chinese  ttys2   Dec  3 22:53   (excalibur)
    cdemmert ttys5   Dec  3 23:00   (mentor)
    yuenca   ttys6   Dec  3 23:00   (mentor)
    janitor  ttys7   Dec  3 18:18   (age)
    mathisbp ttys8   Dec  3 23:17   (dov)
    janitor  ttys9   Dec  3 18:18   (age)
    cs541    ttysC   Dec  2 15:16   (solaria)
    yansong  ttysL   Dec  1 14:44   (math)
    mdps     ttysO   Nov 30 19:39   (localhost)
    md       ttysU   Dec  2 08:45   (muller)
    jac      ttysa   Dec  3 18:18   (localhost)
    eichsted ttysb   Dec  3 23:21   (pc1)
    sweett   ttysc   Dec  3 22:40   (dov)
    "big.output" 40 lines, 1659 characters
    
  2. In the middle of working on this, I suddenly realize that I need to make a slight change to the recently saved buckaroo.confused file. That's where the :e command comes in handy. Using it, I can edit any other file:

    ~
    ~
    :e buckaroo.confused_
    							

    I press Return and see this:

    								I found myself stealing a peek at my own watch and overheard
    General Catbird's
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    "buckaroo.confused" 17 lines, 546 characters
    

That's it! You now know a considerable amount about one of the most important, and certainly most used, commands in UNIX. There's more to learn (isn't there always?), but you now can edit your files with aplomb!


Task 11.3: How to Start vi Correctly

The vi command wouldn't be part of UNIX if it didn't have some startup options available, but there really are only two options worth mentioning. The -R flag sets up vi as a read-only file, to ensure that you don't accidentally modify a file. The second option doesn't start with a dash, but with a plus sign: Any command following the plus sign is used as an initial command to the program. This is more useful than it may sound. The command vi +$ sample, for example, starts the editor at the bottom of the file sample, and vi +17 sample starts the editor on the 17th line of sample.


  1. First, this is the read-only format:

    % vi -R buckaroo
    								I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    "buckaroo" [Read only] 9 lines, 276 characters
    

    Notice the addition of the [Read only] message on the status line. You can edit the file, but if you try to save the edits with :w, you will see this:

    ~
    ~
    "buckaroo" File is read only
    

    Quit vi with :q!.

  2. Next, recall that janitor occurs in many places in the big.output file. I'll start vi on the file line that contains the pattern janitor in the file:

    % vi +/janitor big.output
    brandt   ttyrb   Nov 28 23:03   (age)
    holmes   ttyrj   Dec  3 21:59   (age)
    yuxi     ttyrn   Dec  1 14:19   (pc)
    frodo    ttyro   Dec  3 22:01   (mentor)
    labeck   ttyrt   Dec  3 22:02   (dov)
    chenlx2  ttyru   Dec  3 21:53   (mentor)
    leungtc  ttys0   Nov 28 15:11   (gold)
    chinese  ttys2   Dec  3 22:53   (excalibur)
    cdemmert ttys5   Dec  3 23:00   (mentor)
    yuenca   ttys6   Dec  3 23:00   (mentor)
    janitor  ttys7   Dec  3 18:18   (age)
    mathisbp ttys8   Dec  3 23:17   (dov)
    janitor  ttys9   Dec  3 18:18   (age)
    cs541    ttysC   Dec  2 15:16   (solaria)
    yansong  ttysL   Dec  1 14:44   (math)
    mdps     ttysO   Nov 30 19:39   (localhost)
    md       ttysU   Dec  2 08:45   (muller)
    jac      ttysa   Dec  3 18:18   (localhost)
    eichsted ttysb   Dec  3 23:21   (pc1)
    sweett   ttysc   Dec  3 22:40   (dov)
    wellman  ttysd   Dec  3 23:01   (dov)
    tuttleno ttyse   Dec  3 23:03   (indyvax)
    wu       ttysf   Dec  3 23:10   (term01)
    "big.output" 40 lines, 1659 characters
    

    This time, notice where the cursor is sitting.

  3. Finally, launch vi with the cursor on the third line of the file buckaroo:

    % vi +3 buckaroo
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    "buckaroo" 9 lines, 276 characters
    

    Again, notice where the cursor rests.

At times it can be helpful to know these two starting options. In particular, I often use +/pattern to start the editor at a specific pattern, but you can use vi for years without ever knowing more than just the name of the command itself.


Task 11.4: Search and Replace

Though most of vi is easy to learn and use, one command that always causes great trouble for users is the search-and-replace command. The key to understanding this command is to remember that vi is built on the line editor (ex). Instead of trying to figure out some arcane vi command, it's easiest to just drop to the line editor and use a simple colon command to replace an old pattern with a new one. To replace an existing word on the current line with a new word (the simplest case), use :s/old/new/. If you want to have all occurrences on the current line matched, you need to add the g suffix: :s/old/new/g.


To change all occurrences of one word or phrase to another across the entire file, the command is identical to the preceding command, except that you must prefix an indication of the range of lines affected. Recall that $ is the last line in the file, and that ranges are specified by two numbers separated by a comma. It should be no surprise that the command is :1,$ s/old/new/g.

  1. Start vi again with the buckaroo file.

    Excerpt from "Buckaroo Banzai" by Earl MacRauch
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    Go Team Banzai! Go Team Banzai! Go Team Banzai!
    
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    

    The cursor is on the first line. I'm going to rename Earl. I type :, the cursor immediately moves to the bottom, and then I type s/Earl/Duke/. Pressing Return produces this:

    Excerpt from "Buckaroo Banzai" by Duke MacRauch
    I found myself stealing a peek at my own watch and overheard General
    Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    

    As you can see, this maneuver was simple and effective.

  2. I've decided that development psychology is my bag. Now, instead of having this Banzai character, I want my fictional character to be called Bandura. I could use the preceding command to change the occurrence on the current line, but I really want to change all occurrences within the file.

    This is no problem. I type :1,$ s/Banzai/Bandura/ and press Return. Here's the result:

    Excerpt from "Buckaroo Bandura" by Duke MacRauch
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Bandura."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    Go Team Bandura! Go Team Banzai! Go Team Banzai!
    
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    

    The result is not quite right. Because I forgot the trailing g, vi changed only the very first occurrence on each line, leaving the “go team” exhortation rather confusing.

    To try again, I type :1,$ s/Banzai/Bandura/g and press Return, and the screen changes as desired:

    Excerpt from "Buckaroo Bandura" by Duke MacRauch
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Bandura."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    Go Team Bandura! Go Team Bandura! Go Team Bandura!
    
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    7 substitutions
    

    Notice that vi also indicates the total number of substitutions in this case.

  3. I'll press u to undo the last change.

Search and replace is one area where a windowing system like that of a Macintosh or PC running Windows comes in handy. A windowing system offers different boxes for the old and new patterns; it shows each change and a dialog box asking, “Should I change this one?” Alas, this is UNIX, and it's still designed to run on ASCII terminals.


Task 11.5: The Change and Replace Commands

In the preceding section, you saw me fix various problems by deleting words and then replacing them with new words. There is, in fact, a much smarter way to do this, and that is by using either the change or the replace command.


Each command has a lowercase version and an uppercase version, and each is quite different from the other. The r command replaces the character that the cursor is sitting on with the next character you type, whereas the R command puts you into replace mode so that anything you type overwrites whatever is already on the line until you stop typing. By contrast, C replaces everything on the line with whatever you type. (It's a subtle difference—but I demonstrate it, so don't fear.) The c command is the most powerful of them all. The change command, c, works just like the d command did, as described in the preceding hour. You can use the c command with any address command, and it will enable you to change text through to that address, whether it's a word, a line, or even the rest of the document.

  1. Start vi with the buckaroo.confused file.

    								I found myself stealing a peek at my own watch and overheard
    General Catbird's
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    "buckaroo.confused" 17 lines, 546 characters
    

    Without moving the cursor at all, type R. Nothing happens, or so it seems. Now type the words Excerpt from "Buckaroo Banzai", and watch what happens:

    								Excerpt from "Buckaroo Banzai"at my own watch and overheard
    General Catbird's
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    

    Now press Escape and notice that what you see on the screen is exactly what's in the file.

  2. This isn't, however, quite what I want. I could use either D or d$ to delete through the end of the line, but that's a bit awkward. Instead, I'll use 0 to move back to the beginning of the line. You do so, too:

    								Excerpt from "Buckaroo Banzai" at my own watch and overheard
    General Catbird's
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    

    This time, type C to change the contents of the line. Before you even type a single character of the new text, notice what the line now looks like:

    								Excerpt from "Buckaroo Banzai" at my own watch and overheard
    General Catbird'$
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    

    Here's where a subtle difference comes into play. Look at the last character on the current line. Where the s had been, when you pressed C, the program placed a $ instead to show the range of the text to be changed by the command. Press the Tab key once, and then type Excerpt from "Buckaroo Bansai" by Earl MacRauch.

    								Excerpt from "Buckaroo Bansai" by Earl MacRauchheard General
    Catbird'$
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    

    This time, watch what happens when I press Escape:

    Excerpt from "Buckaroo Bansai" by Earl MacRauch
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    
  3. I think I made another mistake. The actual title of the book is Buckaroo Banzai with a z, but I've spelled it with an s instead. This is a chance to try the new r command.

    Use cursor control keys to move the cursor to the offending letter. I'll use b to back up words and then h a few times to move into the middle of the word. My screen now looks like this:

    Excerpt from "Buckaroo Bansai" by Earl MacRauch
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    

    Now type r. Again, nothing happens; the cursor doesn't move. Type r again to make sure it worked:

    Excerpt from "Buckaroo Banrai" by Earl MacRauch
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    

    That's no good. It replaced the s with an r, which definitely isn't correct. Type rz, and you should have the following:

    Excerpt from "Buckaroo Banzai" by Earl MacRauch
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    
  4. Okay, those are the easy ones. Now it's time to see what the c command can do for you. In fact, it's incredibly powerful. You can change just about any range of information from the current point in the file in either direction!

    To start, move to the middle of the file, where the second copy of the passage is located:

    Excerpt from "Buckaroo Banzai" by Earl MacRauch
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    "buckaroo.confused" 17 lines, 546 characters
    

    I think I'll just change the word aide that the cursor is sitting on to The tall beige wall clock opted to instead. First, I type c and note that, as with many other commands in vi, nothing happens. Now I type w because I want to change just the first word. The screen should look like this:

    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    aid$ give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    

    Again, the program has replaced the last character in the range of the change to a $ so that I can eyeball the situation. Now I type The tall beige wall clock opted to. Once I reach the $, the editor stops overwriting characters and starts inserting them instead; the screen now looks like this:

    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    The tall beige wall clock opted to_give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    

    Press Escape and you're done (though you can undo the change with the u or U commands, of course).

  5. Tall and beige or not, this section makes no sense now, so change this entire line by using the $ motion command you learned in the preceding hour. First, use 0 to move to the beginning of the line, and then type c$:

    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    The tall beige wall clock opted to give him the latest$
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    

    This is working. The last character changed to $. Press Escape, and the entire line is deleted:

    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    _
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    
  6. There are still six lines below the current line. I could delete them and then type the information I want, but that's primitive. Instead, the c command comes to the rescue. Move down one line, type c6, and press Return. Watch what happens:

    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    7 lines changed
    

    In general, you always can change the current and next line by using c followed by a Return (because the Return key is a motion key, too, remember). By prefacing the command with a number, I changed the range from two lines to six.

    Now press Tab four times, type (page 8), and then press the Escape key. The screen should look like this:

    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    
                                    (page 8)
    ~
    ~
    ~
    

You might be asking, “Why two lines?” The answer is subtle. In essence, whenever you use the c command, you change the current line plus any additional lines that might be touched by the command. Pressing Return moves the cursor to the following line; therefore, the current line (starting at the cursor location) through the following line are changed. The command probably should change just to the beginning of the following line, but that's beyond even my control!


  1. What if I change my mind? That's where the u command comes in handy. Typing u once undoes the last command:

    Excerpt from "Buckaroo Banzai" by Earl MacRauch
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    6 more lines
    

The combination of replace and change commands adds a level of sophistication to an editor that you might have suspected could only insert or delete. There's much more to cover in this hour, so don't stop now!


Task 11.6: Accessing UNIX with !

This final task on vi introduces you to one of the most powerful, and least-known, commands in the editor: the ! escape-to-UNIX command. When prefaced with a colon (:!, for example), it enables you to run UNIX commands without leaving the editor. More powerfully, the ! command in vi itself, just like d and c, accepts address specifications, feeds that portion of text to the command, and replaces that portion with the results of having run that command on the text.


Let's have a look.

  1. Let's leave Buckaroo Banzai alone for a bit to switch to a classic, Charles Dickens's A Tale of Two Cities. I've created a file called dickens.note for this exercise, and you can either type it yourself or grab a copy of the file on our Web site, www.intuitive.com/tyu24/. The file is shown here:

    % cat dickens.note
    
                            A Tale of Two Cities
                                 Preface
    
      When I was acting, with my children and friends, in Mr Wilkie Collins's
      drama of The Frozen Deep, I first conceived the main idea of this
      story. A strong desire was upon me then, to
      embody it in my own person;
      and I traced out in my fancy, the state of mind of which it would
      necessitate the presentation
      to an observant spectator, with particular
      care and interest.
    
      As the idea became familiar to me, it gradually shaped itself into its
      present form. Throughout its execution, it has had complete possession
      of me; I have so far verified what
      is done and suffered on these pages,
      as that I have certainly done and suffered it all myself.
    
      Whenever any reference (however slight) is made here to the condition
      of the French people before or during the Revolution, it is truly made,
      on the faith of the most trustworthy
      witnesses. It has been one of my hopes to add
      something to the popular and picturesque means of
      understanding that terrible time, though no one can
      hope to add anything to the philosophy of Mr Carlyle's wonderful book.
    
      Tavistock House
      November 1859
    

    With this file on my system, I'll start by double-checking what files I have in my home directory. To do this, I type :!, which moves the cursor to the bottom line:

    of the French people before or during the Revolution, it is truly made,
    on the faith of the most trustworthy
    witnesses.  It has been one of my hopes to add
    something to the popular and picturesque means of
    :!_
    

    I simply type ls -CF and press Return, as if I were at the % prompt in the command line:

    of the French people before or during the Revolution, it is truly made,
    on the faith of the most trustworthy
    witnesses.  It has been one of my hopes to add
    something to the popular and picturesque means of
    :!ls -CF
    Archives/          big.output         dickens.note       src/
    InfoWorld/         bigfiles           keylime.pie        temp/
    Mail/              bin/               newfile            tetme
    News/              buckaroo           owl.c
    OWL/               buckaroo.confused  sample
    awkscript          demo               sample2
    [Hit any key to continue] _
    

    If I press Return, I'm back in the editor, and I have quickly checked what files I have in my home directory.

  2. Now for some real fun, move to the beginning of the first paragraph and add the text Chuck, here are my current files:. Press Return twice before using the Escape key to return to command mode. My screen now looks like this:

                                       A Tale of Two Cities
                                             Preface
    
    Chuck, here are my current files:
    								_
    When I was acting, with my children and friends, in Mr Wilkie Collins's
    drama of The Frozen Deep, I first conceived the main idea of this
    story.  A strong desire was upon me then, to
    

    Notice that the cursor was moved up a line. I'm now on a blank line, and the line following is also blank.

    To feed the current line to the UNIX system and replace it with the output of the command, vi offers an easy shortcut: !!. When I type the second ! (or, more precisely, once vi figures out the desired range specified for this command), the cursor moves to the bottom of the screen and prompts with a single ! character:

    of the French people before or during the Revolution, it is truly made,
    on the faith of the most trustworthy
    witnesses. It has been one of my hopes to add
    something to the popular and picturesque means of
    :!_
    

    To list all the files in my directory, I can again type ls -CF and press Return. After a second, vi adds the output of that command to the file:

                                    A Tale of Two Cities
                                          Preface
    
    Chuck, here are my current files:
    Archives/               bigfiles                newfile
    InfoWorld/              bin/                    owl.c
    Mail/                   buckaroo                sample
    News/                   buckaroo.confused       sample2
    OWL/                    demo                    src/
    awkscript               dickens.note            temp/
    big.output              keylime.pie             tetme
    
    When I was acting, with my children and friends, in Mr Wilkie Collins's
    drama of The Frozen Deep, I first conceived the main idea of this
    story.  A strong desire was upon me then, to
    embody it in my own person;
    and I traced out in my fancy, the state of mind of which it would
    necessitate the presentation
    to an observant spectator, with particular
    care and interest.
    As the idea became familiar to me, it gradually shaped itself into its
    present form.  Throughout its execution, it has had complete possession
    6 more lines
    

    Notice that this time the status on the bottom indicates how many lines were added to the file.

    Type u to undo this change. Notice that the vi status indicator on the bottom line says there are now six fewer lines.

  3. Move back to the W in When. You are now ready to learn one of the commands I like most in vi. This command enables you to hand a paragraph of text to an arbitrary UNIX command.

    This time I'm going to use the UNIX stream editor “sed” to perform a neat trick: prefacing each selected line with '>'. The actual command I'll use is sed 's/^/> /'. Ready? This is where the } command comes in handy, too. To accomplish this trick, I type !}, moving the cursor to the bottom of the screen, and then type the sed command as you saw earlier: sed 's/^/> /'. Pressing Return feeds the lines to sed. The sed command makes the change indicated and replaces those lines with the output of the sed command. Voila! The screen now looks as shown next.

                                    A Tale of Two Cities
                                          Preface
    
    Chuck, here are my current files:
    
    
    ≥ When I was acting, with my children and friends, in Mr Wilkie Collins's
    > drama of The Frozen Deep, I first conceived the main idea of this
    > story.  A strong desire was upon me then, to
    > embody it in my own person;
    > and I traced out in my fancy, the state of mind of which it would
    > necessitate the presentation
    > to an observant spectator, with particular
    > care and interest.
    
    As the idea became familiar to me, it gradually shaped itself into its
    present form.  Throughout its execution, it has had complete possession
    of me; I have so far verified what
    is done and suffered in these pages,
    as that I have certainly done and suffered it all myself.
    Whenever any reference (however slight) is made here to the condition
    of the French people before or during the Revolution, it is truly made,
    !sed 's/^/> /'
    							

The sed editor is one of your best friends in UNIX because you can use it in any command pipe to modify the data as it passes through. A quick read of the sed man page will be time well spent.


  1. I hope you're excited to see this command in action! It's a powerful way to interact with UNIX while within vi.

    I'll provide a few more examples of ways to interact with UNIX while within vi. First, I don't really want the prefix to each line, so I'm going to type u to undo the change.

    Instead, I would rather have the system actually tighten up the lines, ensuring that a reasonable number of words occur on each line and that no lines are too long. On most systems, there is a command called either fmt or adjust to accomplish this. To figure out which works on your system, simply use the :! command, and feed a word or two to the fmt command to see what happens:

    Whenever any reference (however slight) is made here to the condition
    of the French people before or during the Revolution, it is truly made,
    :!echo hi | fmt
    [No write since last change]
    hi
    [Hit any key to continue] _
    							

    In this case, fmt did what I hoped, so I can be sure that the command exists on my system. If your response was command unknown, adjust is a likely synonym. If neither exists, complain to your vendor!

    Armed with this new command, you can try another variant of !}, this time by feeding the entire paragraph to the fmt command. I'm still at the beginning of the word When in the text. So when I type the command !}fmt, the paragraph is cleaned up, and the screen changes to this:

                                    A Tale of Two Cities
                                          Preface
    
    Chuck, here are my current files:
    
    
    When I was acting, with my children and friends, in Mr Wilkie Collins's
    drama of The Frozen Deep, I first conceived the main idea of this
    story.  A strong desire was upon me then, to embody it in my own
    person; and I traced out in my fancy, the state of mind of which it
    would necessitate the presentation to an observant spectator, with
    particular care and interest.
    
    As the idea became familiar to me, it gradually shaped itself into its
    present form.  Throughout its execution, it has had complete possession
    of me; I have so far verified what
    is done and suffered in these pages,
    as that I have certainly done and suffered it all myself.
    
    Whenever any reference (however slight) is made here to the condition
    of the French people before or during the Revolution, it is truly made,
    on the faith of the most trustworthy
    witnesses.  It has been one of my hopes to add
    2 fewer lines
    

    Again, vi tells us that the number of lines in the file has changed as a result of the command. In this situation, tightening up the paragraph actually reduced it by two display lines.

    This command is so helpful that I often have it bound to a specific key with the map command. A typical way to do this in an .exrc might be this:

    :map ^P !} fmt^M
    

    The ^M is what vi uses to record a Return. (Recall that you need to use the ^v beforehand.) With this defined in my .exrc, I can press ^p to format the current paragraph.

  2. I will provide one more example of the ! command before I wrap up this hour. Remember the awk command that was introduced in Hour 9, “Wildcards and Regular Expressions”? Remember how it can easily be used to extract specific fields of information? This can be tremendously helpful in vi. Rather than continue working with the dickens.intro file, however, I'll quit vi and create a new file containing some output from the ls command:

    % ls -CF
    Archives/          big.output         dickens.note       src/
    InfoWorld/         bigfiles           keylime.pie        temp/
    Mail/              bin/               newfile            tetme
    News/              buckaroo           owl.c
    OWL/               buckaroo.confused  sample
    awkscript          demo               sample2
    % ls -l a* b* > listing
    							

    Now I can use vi listing to start the file with the output of the ls command:

    								-rw-rw----  1 taylor        126 Dec  3 16:34 awkscript
    -rw-rw----  1 taylor       1659 Dec  3 23:26 big.output
    -rw-rw----  1 taylor        165 Dec  3 16:42 bigfiles
    -rw-rw----  1 taylor        270 Dec  4 15:09 buckaroo
    -rw-rw----  1 taylor        458 Dec  4 23:22 buckaroo.confused
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    "listing" 5 lines, 282 characters
    

    It would be nice to use this as the basis for creating a shell script (which is just a series of commands you might type to the shell directly, all kept neatly in a single file). A shell script can show me both the first and the last few lines of each file, with the middle chopped out.

    The commands I'd like to have occur for each file entry are these:

    echo ==== filename ====
    head -5 filename; echo ...size bytes...; tail -5 filename
    

    I'll do this with a combination of the ! command in vi and the awk program with the awk command:

    awk '{  print "echo ==== "$8" ===="; print "head "$8"; echo
    ..."$4"  bytes...; tail "$8}'
    

    With the cursor on the top line of this file, I can now type !G to pipe the entire file through the command. The cursor drops to the bottom of the screen, and then I type the awk script shown previously and press Return. The result is this:

    echo ==== awkscript ====
    head -5 awkscript; echo ...126 bytes...; tail -5 awkscript
    echo ==== big.output ====
    head -5 big.output; echo ...1659 bytes...; tail -5 big.output
    echo ==== bigfiles ====
    head -5 bigfiles; echo ...165 bytes...; tail -5 bigfiles
    echo ==== buckaroo ====
    head -5 buckaroo; echo ...270 bytes...; tail -5 buckaroo
    echo ==== buckaroo.confused ====
    head -5 buckaroo.confused; echo ...458 bytes...; tail -5 buckaroo.confused~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    ~
    !awk '{  print "echo ==== "$8" ===="; print "head "$8"; echo
    ..."$4" bytes...; tail "$8}'-
    

    If I now quit vi and ask sh to interpret the contents, here's what happens:

    % chmod +x listing
    % sh listing
    ==== awkscript ====
    {
            count[length($1)]++
    }
    END {
            for (i=1; i < 9; i++)
    ...126 bytes...
    }
    END {
            for (i=1; i < 9; i++)
              print "There are " counti " accounts with " i " letter names."
    }
    ==== big.output ====
    leungtc  ttyrV   Dec  1 18:27   (magenta)
    tuyinhwa ttyrX   Dec  3 22:38   (expert)
    hollenst ttyrZ   Dec  3 22:14   (dov)
    brandt   ttyrb   Nov 28 23:03   (age)
    holmes   ttyrj   Dec  3 21:59   (age)
    ...1659 bytes...
    buckeye  ttyss   Dec  3 23:20   (mac2)
    mtaylor  ttyst   Dec  3 23:22   (dov)
    look     ttysu   Dec  3 23:12   (age)
    janitor  ttysw   Dec  3 18:29   (age)
    ajones   ttysx   Dec  3 23:23   (rassilon)
    ==== bigfiles ====
    12556   keylime.pie
    8729    owl.c
    1024    Mail/
    582     tetme
    512     temp/
    ...165 bytes...
    512     Archives/
    207     sample2
    199     sample
    126     awkscript
    
    ==== buckaroo ====
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Banzai."
    "Where the hell is he?"
    ...270 bytes...
    "Banzai."
    "Where the hell is he?"
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    ==== buckaroo.confused ====
            Excerpt from "Buckaroo Bandura" by Duke MacRauch
    I found myself stealing a peek at my own watch and overheard
    General Catbird's
    aide give him the latest.
    "He's not even here," went the conversation.
    "Who?"
    "Bandura."
    ...458 bytes...
    "At the hospital in El Paso."
    "What? Why weren't we informed? What's wrong with him?"
    
    Go Team Bandura! Go Team Bandura! Go Team Bandura!
    
    %
    
    

Clearly, the ! command opens up vi to work with the rest of the UNIX system. There's almost nothing you can't somehow manage to do within the editor, whether it's add or remove prefixes, clean up text, or even show what happens when you try to run a command or reformat a passage within the current file.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset