RHCSA: Basic and intermediate set of VIM commands for sysadmins

News Red Hat Certification Program Understanding and using essential tools Access a shell prompt and issue commands with correct syntax Finding Help Managing files in RHEL Working with hard and soft links Working with archives and compressed files Using the Midnight Commander as file manager
Text files processing Using redirection and pipes Use grep and extended regular expressions to analyze text files Finding files and directories; mass operations on files Connecting to the server via ssh, using multiple consoles and screen command Introduction to Unix permissions model Vim Regular Expressions Searching and replacing text in VI VIM Multiwindows Support
Piping Vim Buffer VIM visual blocks File managers in VIM Copying and Moving sections of text Tips Sysadmin Horror Stories Unix History with some Emphasis on Scripting Humor Etc

Vim allows you to access all operations and shell command  from the command line. This is a feature of so called "orthodox editor" (see VIM)

The uniqueness of VIM is that is operated in several "modes", each of modes has it's own  set of command and capabilities:

  1. Regular mode: you can issue command that work with the current line (line on which the cursor resides)

  2. Insert Mode: The Insert mode lets you can insert text in a document. The shortcut is: "i" (insert text where the cursor is) or "o" (insert text at the beginning of the following line).
  3. Visual Mode: The visual mode permits the user to select the text like you would do with a mouse, but using the keyboard instead of the mouse. Useful to copy several lines f text for example. The shortcut is: "V".

  4. Command Mode: Let's now speak about the command mode, a command begins with the symbol ":".

When you are in another mod you can use the escape key (sometimes you'll need to hit it twice) to come back to command mod at any time.

For a more in-depth explanation of the Vim modes, take a look at the vimtutor.

The challenge when working with vim is the vast number of commands that are available. It is just impossible for mere mortal to remember all of them. Although there is some system in this madness ;-) And that help to memorize more command that would be possible otherwise. For example all commands working with buggers start with the letter b.  All command for switching from one window to another  with Ctrl-W, and so on.

Some people have even produced vi cheat sheets, listing all available commands. But that's an overkill.

If you unable or unwilling to learn "intermediate VIM" you can still do most on the things required on the exam using just a dozen of VIM commands.   But that is a handicap. You might better off spending  additional time and getting to "intermediate" level (which is characterized by the ability to use multiple buffers, changes windows layout, use visual selection and registers, and pipe parts or all of the bugger via external filters.

In any case here is the basic set of VIM command:

  1. i  -- switch to the insert mode
  2. a -- switch to append mode
    • A - inserts text after the end of the line.
  3. :w save:
    • :wq -- save and exit:
    • q  exit: :
    • :w! -- forcefully overwrite
    • :q! -- to trash all changes )
  4. :vsplit vertical split: open a document and then type :vsplit /path-to-document/document and this will open the specified document and split the screen so you can see both documents.
  5. y -- copy a line or selection :
  6. yy -- copy a line:
  7. paste: p
  8. o --  opens an empty line below the cursor and switch to Insert mode.
    • O - opens a line above the cursor and switch to Insert mode
  9. x cutsymbol
  10. dd -- cut a line:

It is important to learn to use VIM help and vimtutor command. (Use yum install vim-enhanced to install it.) This command opens a vim tutorial that has you work through some nice additional exercises.

Key concepts

We need to distinguish between buffer, window and view. Buffer is  a block of memory that is allocated when you begin a word-processing session. If you load a file this buffer is a temporary holding area for the files. It is emptied at the end of each session.

To save your work, you have to write the contents of the buffer to a file. A file is a permanent storage area on a disk (a hard disk or a floppy disk). After you have saved your work in a file, you can retrieve it for use in another session.

When you begin a session editing a document that exists on file, a copy of the file is made and its contents are read into the buffer. You actually work on the copy of the document stored in memory. The file is not changed until you save your changes during or at the end of your work session. You can also discard changes made to the buffered copy, keeping the original file intact, or save multiple versions of a document in separate files.

Particularly when working with larger documents, the management of disk files can become a major effort. If, like most writers, you save multiple drafts, it is easy to lose track of which version of a file is the latest. So serious writers use version management system like GIT.

More extended set of command -- 21 commands that get you to the Level A+ ;-)

The command s is the most important addition on this level. The format for the command that perform global change of one sting to another is:

from,to s/old/new/g

Here old and new are placeholders for actual strings and from and to are line numbers for region of the text where replacement should be performed. The optional g means to replace everywhere. Without it, only the first occurrence on each line will be replaced. To replace green with blue in your entire document, use

1,$s/green/blue/g
To replace blue with green in lines 10 through 24 use
10,24:s/blue/green/g

The search and replace command allows regular expression to be used over a range of lines and replace the matching string. The user can ask for confirmation before the substitution is performed.  More examples:

         1,$s/the/The/g      Search the entire file and replace the with The.
         %s/the/The/g        % means the complete file. (Same command as above, only range specification differs).
         .,5s/^.*//g         Delete the contents from the current to 5th line.
         %s/the/The/gc       Replace the with The but ask before substituting.
         10,20s/^.//g         Delete the first characters selected fragment (uncommenting).

The search command is more powerful when combined with the regular expression search strings. If the g directive is not included or range on line is one line then the change is performed only on the first occurrence of a match on each line.

Sometimes you may want to use the original search string in the replacement result. You could retype the command on the line but vi allows the replacement string to contain some special characters.

         1,5s/help/&ing/g    Replaces help with helping on the first 5 lines.
         %s/ */&&/g          Double the number of spaces between the words.

Other 20 commands that you need to lear on this level:

  1. p - puts the previously deleted text after the cursor(Type dd to delete the line and store it in a Vim register. and p to put the line)
  2. r - to replace the letter e.g press re to replace the letter with e
  3. ce - to change until the end of a word (place the cursor on the u in lubw it will delete ubw )
  4. ce - deletes the word and places you in Insert mode
  5. G - to move you to the bottom of the file.
  6. gg - to move you to the start of the file.
    Type the number of the line you were on and then G
  7. % to find a matching ),], or }
  8. :s/old/new/g to substitute 'new' for 'old' where g is globally
  9. / backward search n to find the next occurrence and N to search in opposite direction
  10. ? forward search
  11. :! to run the shell commands like :!dir, :!ls
  12. v - starts visual mode for selecting the lines and you can perform operation on that like d delete
  13. :r - Filename will insert the content into the current file
  14. R - to replace more than one character
  15. y - operator to copy text using v visual mode and p to paste it
  16. yw - (copy)yanks one word
  17. e - command moves to the end of a word.
  18. y - operator yanks (copies) text, p puts (pastes) it.
  19. R - enters Replace mode until <ESC> is pressed.
  20. ctrl-w to jump from one window to another

For more information about intermediate level set of commands see article Vim Revisited  by By or, better, one of free ebook for VIM such as Vim Book

Please note that to reach advanced level of VIM is almost impossible for sysadmins. Only programmers, who chose VIM as their primary editor typically are able  to achieve  this level (with few exceptions).

We also discuss several key command from intermeduate level of VIM below.

Reading output of the Perl (or other) script of program into VIM buffer

Most Vim users are already familiar with using the read command (r), which inserts text from a specified file after the current line in the current buffer:

:r textfile 

What is important is that you can read in the output any script of program. For example:

:r ! ll /home/user/directory

This redirect the output of that command into the buffer and it is inserted after the current line.  This feature is useful for example to read the output of the Web page that you're editing, using a text-mode browser:

:r ! w3m http://en.wikipedia.org/wiki/Vi -dump

The -dump option tells w3m to simply spit out the Web page as plain text and exit.

It's also possible to execute multiple commands connected via pipes, for example

:r ! df -h | sort -r
:r ! ls -a | egrep -v '^_'

Effectively, we’re putting our shell command directly after the ! character, and when we execute this command, Vim is placed in a background process while the shell command is executed. Once the shell command is finished, the resulting output is placed into our buffer, directly beneath our current cursor position.

The read command might also be useful for creating a report about the incident the you are resolving by allowing you to add to your report fragments from logs and execution of necessary commands:

:r ! grep string /var/log/apache2/site-error.log

Vim also makes it easy to redirect the output of most standard Unix utilities into a file, and to pipe text from the file it's editing into standard Unix filters as well as Perl and AWK interpreters.

Piping all or part of the buffer via external filter

Even more useful feature of Vim is ability to pipe part of the buffer into script and then replace this part with the output of the script. That this feature can be used for example for beatifying your script or for commenting out sections of  your programs.  You can pipe all the buffer, or only your selection.

For example,  to pipe all the buffer you need to specify the filer (which can be written by you Perl script) after ! command:

:1,$ ! perltidy

will beautify your program using perltidy.  Beautifying your script is a classic example of using piping in vi. You can also create a macro using keystroke remapping. Instead of beautifier you can use any other filter. This way for example you can temporary remove all comments from the script as it simplifies understanding  and then reread the file with comments back into the buffer:

To do the same for selection you need to provide boundary of selection to the command. The easiest way to do this is to use visual mode:  v, V, or Ctrl-v commands to select the part of your script that you want to process. In this  case boundary of your selection are defined by two mark '< and '> which represent upper and lower boundary correspondingly. They will be put on the command like automatically as soon as you enter : .  For example:

'<,'>! perl -nle 'print "\#".$_'

(this operation is called "commenting out" and it can also be performed via a plugin, but it is a still a good illustration of using Perl filters with VIM).

You can return to original text is you pipe worked incorrectly

Vim will run pass your selection to the script as STDIN  and insert standard output in place of it. If you incorrectly overwrite your selection or the whole buffer you can restore it using undo command (u). As buffer is an "in-memory" mapping of the file, rereading file from the disk using r command also allows you to restore the original text.

Repeating previous pipe command

To repeat the previous pipe command, you need to type:

! object !

Three important VIM concepts: File, buffers, and windows

It is important to distinguish between file, buffer and window. Those are three key concepts of VIM editor:

The :ls command gives us a listing of all the buffers that have been loaded into memory (:ls). We can switch to the next buffer in the list by running the :bnext (can be abbreviated to bn) command or bprev (can be abbreviated to bp). The %  symbol in this list indicates which of the buffers is visible in the current window, while the #  symbol represents the alternate file. We can quickly toggle between the current and alternate files by pressing <C-^>. Press it once, and we’ll switch to a.txt; press it a second time, and we’ll get back to b.txt.

We can traverse the buffer list using four commands—:bp and :bn (or bprev and bnext)  to move backward and forward one at a time, and :bfirst  and :blast  to jump to the start or end of the list. It’s a good idea to map them to something easier to reach. Some users can benefit from more concile mapping taken from  Tim Pope’s unimpaired.vim plugin:

nnoremap <​silent​> [​b​ :​bprevious​​ 
nnoremap <​silent​> ]​b​ :​bnext​​ 
nnoremap <​silent​> [B :​bfirst​ 
nnoremap <​silent​> ]B :​blast​

NOTE: Vim already uses the [  and ]  keys as prefixes for a series of related commands (see [), so these mappings have a consistent feel to them. The unimpaired.vim plugin provides similar mappings for scrolling through the argument ([a  and ]a), quickfix ([q  and ]q), location ([l  and ]l), and tag lists ([t  and ]t). Check it out.)

The :ls  listing starts with the buffer serial number, which is assigned to each buffer automatically on creation. We can jump directly to a buffer by number, using the :bN  command Alternatively, we can use buffer names instead of numbers :b {bufname}. The {bufname} need only contain enough characters from the filepath to uniquely identify the buffer. If we enter a string that matches more than one of the items in the buffer list, we can use tab-completion

Vim creates a new buffer any time we open a file. If we want to delete a buffer, we can do so using the :bdelete command. This can take one of these forms:

:bdelete N1 N2 N3
:N,M bdelete

Note that deleting a buffer has no effect on its associated file; it simply removes the in-memory representation. If we wanted to delete buffers numbered 5 through 10 inclusive, you need to run the command :5,10bd. But if you wanted to keep buffers number 6, 7 and 8, then run :bd 5 9 10.

Buffer numbers are automatically assigned by Vim, and we have no means of changing them by hand. So if we want to delete one or more buffers, we first have to look them up to find out their numbers. Unless I have a good reason to delete a buffer, I usually don’t bother. As a result, the :ls  listing comes to represent all of the files that I have opened in the course of an editing session.

If we want to arrange buffers in a way that makes more sense for our workflow we can use split windows and tabs. VIM associates each file with a buffer and can have multiple buffers opened. Some people open as much as 300 buffers  in VIM.

Some additional useful command:

Opening files and replacing the  content of the buffer (e command)

Vim allows  to open files both from within Vim and from outside of Vim (by supplying the list of files as parameters). This can also be a single file or multiple files. If we specify multiple files you can use basic regular expression to define a group of files. If we wanted to open multiple files at once, we could manually specify them like so:

vim file1.txt file2.txt

Or if you want simultaneously split your window in  subwindows for each file and view all files on the screen at once use:

vim -o file1.txt file2.txt

Within vim you can open the file using the “edit” command (:e), followed by the path to the file. To open a file within Vim, you’ll have to run the following command (the path can either be absolute or relative to the current working directory):

:e /path/to/your/file.txt

You can always  reload the same file, wiping out you changes

:e! %

Edit command without argument will wipe out your changes and restore the state of the files before the last write to it.

Each loaded files is represented in VIM as a buffer. In other words a buffer is a file loaded into memory for editing. The original file remains unchanged until you write the buffer to the file.

Saving the buffer into the file

It’s best for beginners to always be explicit and to use the word buffer, as it cements the idea of how Vim actually modifies buffers and not files.

Let’s look at a few different options for saving a file (which, as we should now know, really means we want to write our buffer back to the source file). The following command is known as the “write” command (we saw this in the last chapter when discussing how buffers work). It’s fairly straightforward, in that it does what you would expect from its name, and writes the buffer content back to the source file.

:w

You can also choose to “save and close,” by running the following composite command (by that I simply mean that we have combined two commands, the “write” command, :w, and the “quit” command, :q):

:wq

Note:  If you prefer something a little more concise (well, one character less), you can use the alternative :x command, which differs only slightly, in that it will only write the buffer when a modification is actually detected.

For example, if we had a file with 10 lines of content and in which every line was modified in some way, we could choose to write only the changes on lines 5–9, by using the following command:

:5,9wq

It’s important to realize that if you have one window displayed on the screen, but multiple buffers open, it might not be clear that you have other buffers open at the same time and if some of those hidden buffers have been modified or not. If you were to try and quit Vim while some buffers had unsaved modifications, Vim would complain by throwing an error at you. If this happens, there are a few options available to you.

  1. Quit Vim and ignore any modified buffers (e.g., your changes will be lost). To do this, you would run the “quit all” command, followed by an exclamation mark, :qa!.
  2. Write all modified buffers and then quit (this will still throw an error if some buffers are read-only or can’t be written for some other reason). To do this, you would run the “write and quit all” command, :wqa.
  3. Ask Vim to write all modified buffers but to let you know of any problems before attempting to quit. To do this, you would run the “write and quit all” command but precede it with the “confirm” command, :conf wqa.
  4. Write all modified buffers, and override even those buffers that are read-only. To do this, you would run the “write and quit all” command, followed by an exclamation mark, :wqa!.

Creating new buffers

VIM load each file into its own buffer and that's the most common way of creating buffers in VIM.  But you can create an empty buffer and then load file into it too. A fresh empty buffer is called a [No Name] buffer. Vim provides us with a few ways to create a new empty buffer. Let’s review each of them.

Switching Working Directories

Now that we have a bit of an understanding of what file name modifiers are in Vim, we can look at another way to take advantage of them. In this example, we’ll look at how we can change the working directory of our project while we’re already inside Vim.

Let’s quickly clarify what the problem is that we’re trying to solve. If we are inside the folder ~/Code/ProjectA/ and we open Vim (let’s also assume we have some files from ProjectA open as well at this point), then Vim’s working directory will be ProjectA. Meaning, if we decide that we need to find some content that we know is inside another project directory (e.g., ~/Code/ProjectB/), we won’t be able to do that without either restarting Vim from within the ProjectB folder, finding the file and then jumping back to ProjectA, or opening a new shell and running Vim from the ProjectB folder and finding the file we’re after. (A real-world example for me is that I need to find a snippet of code I know I’ve used in another project, and so I want to copy it over to this project.)

Ideally, we would like to temporarily change the working directory while still inside the ProjectA folder, so we could find the file in ProjectB and then change the working directory back again to ProjectA. Using a combination of file name modifiers and Vim’s built-in cd command, this is not only possible but allows us to implement in a much simpler way. First, take a look at the following command:

:cd ~/Code/ProjectB