VI Advanced - Ex Commands and Customization
Welcome to Advanced VI
You've mastered the intermediate techniques. Now it's time to learn the deep power of ex commands, extensive customization options, and the techniques that make VI a complete development environment.
What You'll Master:
- Ex mode and its powerful line-editing commands
- Advanced ex command patterns
- Complete .exrc/.vimrc customization
- Abbreviations and mappings
- Advanced text manipulation
- Integration with shell and external tools
- Building your perfect VI environment
Understanding Ex Mode
Ex is the line editor that VI is built on top of. Understanding ex commands gives you incredible power.
Entering Ex Mode
Q # Enter ex mode (traditional vi)
: # Execute single ex command
:visual # Return to visual mode from ex mode
Note: Most people never enter full ex mode (Q). Instead, they use individual ex commands with :. However, understanding ex commands is crucial for advanced usage.
Ex Command Structure
:[range]command[options]
# Examples:
:5d # Delete line 5
:1,10d # Delete lines 1-10
:%s/old/new/g # Substitute in all lines
:g/pattern/d # Delete all lines matching pattern
Advanced Ex Commands
Line Addressing
| Address |
Meaning |
. |
Current line |
$ |
Last line |
% |
All lines (same as 1,$) |
n |
Line number n |
'a |
Line with mark a |
/pattern/ |
Next line matching pattern |
?pattern? |
Previous line matching pattern |
+n |
n lines forward from current |
-n |
n lines backward from current |
Complex Range Examples
:.,$d # Delete from current line to end
:1,.d # Delete from start to current line
:'a,'bd # Delete from mark a to mark b
:/start/,/end/d # Delete from "start" to "end"
:.+5,.+10d # Delete 5 lines ahead through 10 lines ahead
:/^class/,/^def/d # Delete from "class" line to "def" line
:?^import?,/^def/p # Print from last import to next def
The Copy Command
:t # Copy (t = "to")
:co # Same as :t
# Examples:
:5t. # Copy line 5 to after current line
:1,5t$ # Copy lines 1-5 to end of file
:'a,'bt10 # Copy marks a-b to after line 10
:.t0 # Copy current line to start of file
:/pattern/t. # Copy next line with pattern to current position
The Move Command
:m # Move
# Examples:
:5m. # Move line 5 to after current line
:1,5m$ # Move lines 1-5 to end of file
:'a,'bm10 # Move marks a-b to after line 10
:.m0 # Move current line to start of file
The Global Command Deep Dive
:g/pattern/command # Execute command on matching lines
:g!/pattern/command # Execute on non-matching lines
:v/pattern/command # Same as g! (inverse global)
# Multiple commands with |
:g/pattern/d | s/foo/bar/
# Examples:
:g/TODO/m$ # Move all TODO lines to end
:g/^#/t$ # Copy all comment lines to end
:g/ERROR/y A # Append all ERROR lines to buffer a
:g/^$/d # Delete all blank lines
:v/pattern/d # Keep only lines with pattern
:g/pattern/-1d # Delete line before each match
:g/pattern/+1d # Delete line after each match
:g/^/m0 # Reverse file (move each line to top)
:g/pattern/normal @q # Run macro q on matching lines
COMPLEX EXAMPLE: Reorganize Function Definitions
# Move all private functions (starting with _) to end
:g/^def _/m$
# Copy all class definitions to a new file
:g/^class/w >> classes.txt
# Delete all lines between "START" and "END" markers
:g/START/,/END/d
TRY IT NOW: Create a file with mixed content. Use :g/ERROR/t$ to copy all ERROR lines to end. Use :v/ERROR/d to delete everything except ERROR lines (undo first to keep original).
Advanced Substitution Techniques
Substitution Flags and Modifiers
| Flag |
Meaning |
g |
Global (all occurrences on line) |
c |
Confirm each substitution |
i |
Case insensitive |
I |
Case sensitive (override default) |
e |
Suppress error if pattern not found |
& |
Repeat last substitution |
Advanced Replacement Patterns
# Using captured groups
:%s/\(\w\+\) \(\w\+\)/\2 \1/ # Swap two words
# Using special characters in replacement
:%s/pattern/&/ # & = matched text
:%s/\(.*\)/[\1]/ # Wrap in brackets
# Case conversion (vim)
:%s/\w\+/\U&/g # Uppercase matched text
:%s/\w\+/\L&/g # Lowercase matched text
:%s/\w\+/\u&/g # Capitalize first letter
:%s/_\(\w\)/\u\1/g # snake_case to camelCase
# Using expressions (vim)
:%s/\d\+/\=submatch(0)+1/g # Increment all numbers
:%s/^/\=line('.'). '. '/ # Add line numbers
:%s/$/\=strftime("%Y-%m-%d")/ # Add date to end of lines
# Complex patterns
:%s/\v(\d{3})-(\d{3})-(\d{4})/(\1) \2-\3/g # Format phone numbers
:%s/\v(\w+)@(\w+)\.(\w+)/<\1@\2.\3>/g # Wrap emails in <>
Substitution in Specific Contexts
# Only in lines matching pattern
:g/function/s/old/new/g
# Only in lines NOT matching pattern
:v/comment/s/old/new/g
# In a range
:5,20s/old/new/g
# From mark to mark
:'a,'bs/old/new/g
# In visual selection (automatic after V)
# Select with V, then:
:s/old/new/g
PRACTICAL EXAMPLE: Clean Up CSV Data
# Remove quotes
:%s/"//g
# Convert spaces to commas
:%s/\s\+/,/g
# Remove empty fields
:%s/,,/,/g
# Add header
:1i
Name,Age,City
.
# Quote fields with spaces
:%s/\([^,]*\s[^,]*\)/"\1"/g
Text Object Manipulation
Sorting and Filtering
# Sort entire file
:%!sort
# Sort specific range
:5,20!sort
# Sort and remove duplicates
:%!sort -u
# Reverse sort
:%!sort -r
# Numeric sort
:%!sort -n
# Sort by column
:%!sort -k2 # Sort by second column
# Case-insensitive sort
:%!sort -f
# Sort in visual selection
# Select with V, then:
:!sort
Unix Command Integration
# Format as columns
:%!column -t
# Number lines
:%!nl
:%!cat -n
# Remove duplicates (keeping first occurrence)
:%!uniq
# Count lines, words, characters
:%!wc
# Filter through awk
:%!awk '{print $1, $3}' # Print columns 1 and 3
# Filter through sed
:%!sed 's/old/new/g'
# Indent with expand
:%!expand -t4 # Convert tabs to 4 spaces
# JSON formatting (if jq available)
:%!jq .
# XML formatting (if xmllint available)
:%!xmllint --format -
# Compress whitespace
:%!tr -s ' '
# Reverse lines
:%!tac
:g/^/m0 # Alternative: move each line to top
PRACTICAL EXAMPLE: Log File Analysis Pipeline
# Start with raw log
:e application.log
# Extract just timestamps and error messages
:%s/^\(\d\{4}-\d\{2}-\d\{2} \d\{2}:\d\{2}:\d\{2}\).*ERROR: \(.*\)/\1 \2/
# Remove lines that didn't match (will be unchanged)
:v/^\d\{4}/d
# Sort by timestamp
:%!sort
# Count occurrences of each error
:%!uniq -c
# Sort by frequency
:%!sort -rn
# Save result
:w error_summary.txt
File and Buffer Management
Reading and Writing
:r filename # Read file after current line
:r !command # Read command output
:0r filename # Read file at start
:$r filename # Read file at end
:5r filename # Read file after line 5
# Write variations
:w # Write current file
:w filename # Write to filename
:w >> filename # Append to filename
:5,20w filename # Write lines 5-20
:'a,'bw filename # Write marked range
:w !command # Pipe to command
:w !sudo tee % # Save with sudo
:.w !sh # Execute current line in shell
:%!python # Execute file as Python
# Partial file operations
:e +25 filename # Open at line 25
:e +/pattern filename # Open at pattern
:e filename | 25 # Open and go to line 25
File Information
:f # Show filename and position
:f newname # Rename buffer
Ctrl+g # Show file info
1 Ctrl+g # Show full path
:file # Show file info
:ls # List buffers (vim)
:b3 # Switch to buffer 3 (vim)
:bd # Delete buffer (vim)
Customization - The .exrc File
Your ~/.exrc (or ~/.vimrc for vim) contains your VI configuration.
Basic .exrc Structure
Sample ~/.exrc file:
" Basic settings
set number " Show line numbers
set autoindent " Auto-indent new lines
set shiftwidth=4 " Indent width
set tabstop=4 " Tab width
set showmatch " Highlight matching brackets
set ignorecase " Case-insensitive search
set smartcase " Override ignorecase if uppercase used
set hlsearch " Highlight search results
set incsearch " Incremental search
set ruler " Show cursor position
set showmode " Show current mode
set wrapscan " Search wraps around end
set magic " Use magic patterns
" Vi compatibility (in vim)
set nocompatible " Use vim enhancements
" File handling
set autowrite " Auto-save before :next, :make, etc.
set backup " Keep backup files
set backupdir=~/.vim/backup " Backup directory
" Display
set nowrap " Don't wrap long lines
set scrolloff=5 " Keep 5 lines visible above/below cursor
set laststatus=2 " Always show status line
" Editing
set backspace=indent,eol,start " Allow backspace over everything
set expandtab " Use spaces instead of tabs
set smarttab " Smart tab behavior
Essential Settings Reference
| Setting |
What It Does |
set number / set nu |
Show line numbers |
set nonumber / set nonu |
Hide line numbers |
set autoindent / set ai |
Auto-indent new lines |
set tabstop=4 / set ts=4 |
Tab width = 4 spaces |
set shiftwidth=4 / set sw=4 |
Indent width = 4 spaces |
set expandtab / set et |
Use spaces instead of tabs |
set ignorecase / set ic |
Case-insensitive search |
set smartcase / set scs |
Case-sensitive if caps in search |
set hlsearch / set hls |
Highlight search results |
set incsearch / set is |
Show matches while typing |
set showmatch / set sm |
Highlight matching brackets |
set ruler |
Show line/column in status |
set wrap |
Wrap long lines |
set nowrap |
Don't wrap long lines |
# View current setting
:set number?
# Toggle setting
:set number!
# View all settings
:set all
# View only changed settings
:set
Abbreviations
Abbreviations automatically expand short text into longer strings.
Defining Abbreviations
:ab teh the # Fix typo
:ab myemail user@example.com
:ab todo TODO(username):
:ab dts `date +%Y-%m-%d`
In .exrc File
" Common typos
ab teh the
ab recieve receive
ab seperate separate
" Email and signatures
ab myemail john.doe@company.com
ab myname John Doe
" Code snippets
ab pyhead #!/usr/bin/env python3
ab shhead #!/bin/bash
ab todo TODO(jdoe):
ab fixme FIXME(jdoe):
" Templates
ab ifmain if __name__ == '__main__':
ab forloop for i in range():
Managing Abbreviations
:ab # List all abbreviations
:ab myemail # Show specific abbreviation
:una myemail # Remove abbreviation
:abc # Clear all abbreviations
Note: Abbreviations only expand when you type a non-word character (space, punctuation) after them.
TRY IT NOW: Add :ab myname Your Name to your session. Type "myname " (with space) in insert mode and watch it expand.
Key Mapping
Mappings let you create custom keybindings and shortcuts.
Basic Mapping
:map key sequence # Map in command mode
:map! key sequence # Map in insert mode
:imap key sequence # Insert mode (vim)
:nmap key sequence # Normal mode (vim)
:vmap key sequence # Visual mode (vim)
Useful Mappings
" Function keys
map #1 :w^M " F1 = save (^M is Enter)
map #2 :wq^M " F2 = save and quit
map #3 :q!^M " F3 = quit without save
" Leader key mappings (vim, requires 'let mapleader')
let mapleader = ","
map <leader>w :w<CR> " ,w = save
map <leader>q :q<CR> " ,q = quit
map <leader>n :set number!<CR> " ,n = toggle numbers
" Quick edits
map ,v :e ~/.vimrc<CR> " ,v = edit vimrc
map ,s :source ~/.vimrc<CR> " ,s = reload vimrc
" Navigation
map <Space< <964C-f> " Space = page down
map <C-n> :n<CR> " Ctrl+n = next file
map <C-p> :prev<CR> " Ctrl+p = previous file
" Insert mode mappings
imap jj <Esc> " jj = escape (vim)
imap <C-d> <C-r>=strftime("%Y-%m-%d")<CR> " Ctrl+d = date
" Comment toggling
map ,c :s/^/# /<CR> " ,c = comment line
map ,u :s/^# //<CR> " ,u = uncomment line
" Search
map <leader>h :noh<CR> " ,h = clear search highlight
Special Key Notations (VIM)
| Notation |
Key |
<CR> |
Enter/Return |
<Esc> |
Escape |
<Space> |
Space bar |
<Tab> |
Tab |
<C-x> |
Ctrl+x |
<S-x> |
Shift+x |
<A-x> or <M-x> |
Alt+x |
<F1>-<F12> |
Function keys |
<leader> |
Leader key (configurable) |
Viewing and Removing Maps
:map # List all mappings
:map key # Show mapping for key
:unmap key # Remove mapping
:mapclear # Clear all mappings
:imap # List insert mode mappings
:iunmap key # Remove insert mapping
PRACTICAL EXAMPLE: Development Mappings
" Python development
map ,r :!python %<CR> " ,r = run current file
map ,t :!pytest %<CR> " ,t = test current file
map ,p oimport pdb; pdb.set_trace()<Esc> " ,p = add breakpoint
" Quick commenting
vmap ,c :s/^/# /<CR> " Visual: ,c = comment
vmap ,u :s/^# //<CR> " Visual: ,u = uncomment
" File operations
map ,w :w<CR> " ,w = save
map ,x :x<CR> " ,x = save and quit
map ,e :e
" Format code
map ,f gg=G`` " ,f = format entire file
TRY IT NOW (VIM): Add :map ,w :w<CR> then try pressing ,w to save.
Advanced .vimrc Configuration
For vim users, here's a comprehensive .vimrc to use as a starting point:
" ====================
" Basic Settings
" ====================
set nocompatible " Use vim features
syntax on " Syntax highlighting
filetype plugin indent on " File type detection
" Display
set number " Line numbers
set relativenumber " Relative line numbers
set ruler " Show cursor position
set showcmd " Show partial commands
set showmode " Show current mode
set laststatus=2 " Always show status line
set cursorline " Highlight current line
set wildmenu " Command completion menu
set scrolloff=5 " Lines to keep visible
set colorcolumn=80 " Highlight column 80
" Search
set hlsearch " Highlight search results
set incsearch " Incremental search
set ignorecase " Case-insensitive search
set smartcase " Smart case sensitivity
" Editing
set autoindent " Auto-indent
set smartindent " Smart indent
set expandtab " Spaces instead of tabs
set tabstop=4 " Tab = 4 spaces
set shiftwidth=4 " Indent = 4 spaces
set softtabstop=4 " Backspace deletes 4 spaces
set backspace=indent,eol,start " Allow backspace
set showmatch " Show matching brackets
set matchtime=2 " Bracket match time
" Files
set autowrite " Auto-save
set autoread " Auto-reload changed files
set backup " Keep backups
set backupdir=~/.vim/backup// " Backup directory
set directory=~/.vim/swap// " Swap directory
set undofile " Persistent undo
set undodir=~/.vim/undo// " Undo directory
" Performance
set lazyredraw " Don't redraw during macros
set updatetime=300 " Faster updates
" ====================
" Key Mappings
" ====================
let mapleader = ","
" Save and quit
nnoremap <leader>w :w<CR>
nnoremap <leader>q :q<CR>
nnoremap <leader>x :x<CR>
" Navigation
nnoremap <C-h> <C-w>h
nnoremap <C-j> <C-w>j
nnoremap <C-K><C-w>k
nnoremap <C-l> <C-w>l
" Clear search highlight
nnoremap <leader>h :noh<CR>
" Toggle options
nnoremap <leader>n :set number!<CR>
nnoremap <leader>r :set relativenumber!<CR>
nnoremap <leader>p :set paste!<CR>
" Quick edit vimrc
nnoremap <leader>ev :e $MYVIMRC<CR>
nnoremap <leader>sv :source $MYVIMRC<CR>
" Comment toggle (adjust for file type)
nnoremap <leader>c :s/^/# /<CR>:noh<CR>
nnoremap <leader>u :s/^# //<CR>:noh<CR>
vnoremap <leader>c :s/^/# /<CR>:noh<CR>
vnoremap <leader>u :s/^# //<CR>:noh<CR>
" ====================
" Abbreviations
" ====================
iab pyhead #!/usr/bin/env python3
iab shhead #!/bin/bash
iab @@ your.email@example.com
" ====================
" Auto Commands
" ====================
" Remove trailing whitespace on save
autocmd BufWritePre * :%s/\s\+$//e
" Return to last edit position
autocmd BufReadPost *
\ if line("'\"") > 0 && line("'\"") <= line("$") |
\ exe "normal! g`\"" |
\ endif
" File type specific settings
autocmd FileType python setlocal ts=4 sw=4 et
autocmd FileType javascript setlocal ts=2 sw=2 et
autocmd FileType html setlocal ts=2 sw=2 et
autocmd FileType yaml setlocal ts=2 sw=2 et
" ====================
" Status Line
" ====================
set statusline=%f " Filename
set statusline+=%m " Modified flag
set statusline+=%r " Readonly flag
set statusline+=%= " Right align
set statusline+=%y " File type
set statusline+=\ %l/%L " Line/total
set statusline+=\ %c " Column
set statusline+=\ %P " Percentage
" ====================
" Colors
" ====================
set background=dark
" colorscheme desert " Uncomment if available
Note: Create necessary directories:
mkdir -p ~/.vim/backup ~/.vim/swap ~/.vim/undo
Advanced Editing Techniques
Working with Paragraphs
{ # Jump to previous paragraph
} # Jump to next paragraph
dap # Delete around paragraph
yap # Yank around paragraph
gq} # Format to next paragraph
gqap # Format paragraph
" Format text to width
:set textwidth=80
gqG # Format from cursor to end
Case Conversion
~ # Toggle case of character
g~w # Toggle case of word
gUw # Uppercase word
guw # Lowercase word
gUU # Uppercase line
guu # Lowercase line
# In visual mode
U # Uppercase selection
u # Lowercase selection
~ # Toggle case of selection
Increment/Decrement Numbers
Ctrl+a # Increment number under cursor
Ctrl+x # Decrement number under cursor
10 Ctrl+a # Increment by 10
# Visual block increment (vim)
Ctrl+v # Visual block mode
select numbers
g Ctrl+a # Increment sequentially (1,2,3...)
Digraphs (Special Characters)
# In insert mode:
Ctrl+k char1 char2 # Insert digraph
# Common digraphs:
Ctrl+k << : «
Ctrl+k >> : »
Ctrl+k 12 : ½
Ctrl+k 14 : ¼
Ctrl+k (c : ©
Ctrl+k Rg : ®
:digraphs # List all digraphs
Session Management (VIM)
# Save session
:mksession ~/my-session.vim
:mksession! ~/my-session.vim " Overwrite existing
# Load session
:source ~/my-session.vim
# Or from command line:
vim -S ~/my-session.vim
# What's saved in session:
" - Window layout
" - Working directory
" - File buffers
" - Cursor positions
" - Marks
Add to .vimrc for auto-session:
" Auto-save session on quit
autocmd VimLeave * mksession! ~/.vim/session.vim
" Load last session
nnoremap <leader>ss :source ~/.vim/session.vim<CR>
Integration with Development Tools
Running External Commands
:!command # Run shell command
:.!command # Filter current line through command
:%!command # Filter entire file through command
:5,10!command # Filter lines 5-10
# Examples:
:!make # Run make
:!git status # Git status
:.!date # Replace line with date
:%!python # Execute file as Python
:5,10!sort # Sort lines 5-10
Reading Command Output
:r !ls -la # Insert directory listing
:r !date # Insert current date
:r !git log -5 # Insert recent commits
:r !grep -r pattern * # Insert search results
Vim with Make
:make # Run make
:cn # Next error
:cp # Previous error
:cl # List errors
:cc # Show current error
:copen # Open quickfix window
:cclose # Close quickfix window
Vim with Grep
:grep pattern files # Run grep
:cn # Next match
:cp # Previous match
:copen # Open results
# Example:
:grep -r "TODO" *.py
:copen
Power User Workflows
WORKFLOW 1: Code Review Preparation
# Extract all TODO comments
:g/TODO/y A
# Create review file
:e review.txt
"ap
# Add line numbers and format
:%!nl
:%s/$/ [ ]/
# Result:
1 TODO: Fix authentication [ ]
2 TODO: Add error handling [ ]
3 TODO: Update documentation [ ]
WORKFLOW 2: Config File Templating
# Read template
:r ~/.templates/nginx.conf
# Use macro to customize
qa
/SERVER_NAME
cw
ESC
/PORT
cw
ESC
j
q
# Apply to multiple blocks
@a
@a
@a
WORKFLOW 3: Database Result Formatting
# Paste raw SQL output
:r !mysql -e "SELECT * FROM users"
# Format as table
:%!column -t
# Convert to CSV
:%s/\s\+/,/g
# Or convert to JSON (with jq)
:%!jq -R 'split(",") | {id: .[0], name: .[1], email: .[2]}'
WORKFLOW 4: Batch File Generation
# Create list of files to generate
:e filelist.txt
file1
file2
file3
# Record macro to create files
qa
yy
:e <C-r>".py<CR>
idef main():
pass
if __name__ == '__main__':
main()
<Esc>
:wq<CR>
q
# Apply to all lines
:e filelist.txt
@a
@a
@a
Troubleshooting and Recovery
Recovering from Swap Files
# If you see swap file warning:
:recover " Recover the file
:e " Reload
:q! " Quit without saving
# List swap files
:sw
# Delete swap file after recovery
:!rm .filename.swp
Dealing with Locked Files
:e! filename " Force edit
:w !sudo tee % " Save with sudo
:set noreadonly " Remove readonly flag
Fixing Common Issues
# Terminal messed up after Ctrl+Z
:shell
fg
reset
# Undo tree corrupted
:earlier 1h " Go back 1 hour
:later 30m " Go forward 30 minutes
# File encoding issues
:set fileencoding=utf-8
:w
Performance Tips
Optimization Techniques:
- Use
:noh to clear search highlighting when done
- Disable plugins temporarily:
vim --noplugin
- Use
:set lazyredraw for faster macros
- Profile startup time:
vim --startuptime timelog.txt
- Use
:set synmaxcol=200 for long lines
- Disable swap for temporary files:
:set noswapfile
# Profile vim startup
vim --startuptime startup.log
cat startup.log
# Identify slow plugins
# Disable one at a time and test
# Speed up large files
:syntax off
:set nowrap
:set norelativenumber
What's Next?
Congratulations! You've mastered advanced VI techniques. You now know:
- Ex mode and complex ex commands
- Advanced substitution and text manipulation
- Complete .exrc/.vimrc customization
- Abbreviations and custom mappings
- Integration with external tools
- Power user workflows
- Performance optimization
The next tutorial covers power user secrets, efficiency tricks, and advanced VI techniques that make you unstoppable.
Created for Linux System Administrators | Part 4 of the VI Learning Series
Your VI environment is now a powerful development tool!
← Back to VI Index
↑ Back to EXPANDED