Regex Session 07: vim Regex

vim has its own regex flavor with unique quirks. Master vim regex and you can transform any file without leaving your editor.

vim Regex Modes

vim has four "magic" modes that change regex behavior:

Mode Prefix Behavior

magic (default)

(none)

Some chars need escaping: +, ?, |, (), {}

very magic

\v

ERE-like: +, ?, |, (), {} work without escaping

nomagic

\M

Only ^ and $ are special

very nomagic

\V

Nothing is special (literal matching)

Recommendation: Use \v (very magic) for consistency with grep -E.

Search Basics

Command Purpose

/pattern

Search forward

?pattern

Search backward

n

Next match

N

Previous match

*

Search for word under cursor

#

Search backward for word under cursor

Lesson 1: Very Magic Mode

Use \v at the start of pattern for cleaner syntax.

" Without \v (magic mode) - need to escape
/\(foo\|bar\)\+

" With \v (very magic) - cleaner
/\v(foo|bar)+

Practical Searches

" Find IP addresses
/\v\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}

" Find MAC addresses
/\v([A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}

" Find email addresses
/\v[A-Za-z0-9._%+-]+\@[A-Za-z0-9.-]+\.[A-Za-z]{2,}

" Find function definitions (Python)
/\vdef \w+\(

" Find variable assignments
/\v^\s*[a-z_]\w*\s*\=

Lesson 2: Substitution

Syntax: :[range]s/pattern/replacement/flags

Basic Substitutions

" Replace first occurrence on current line
:s/old/new/

" Replace all on current line
:s/old/new/g

" Replace all in file
:%s/old/new/g

" Replace with confirmation
:%s/old/new/gc

" Case-insensitive
:%s/old/new/gi

Range Specifiers

" Current line
:s/old/new/g

" Lines 5-10
:5,10s/old/new/g

" From current to end
:.,$s/old/new/g

" Entire file
:%s/old/new/g

" Lines matching pattern
:g/pattern/s/old/new/g

" Visual selection
:'<,'>s/old/new/g

Lesson 3: Capture Groups

vim uses \( and \) for capturing (or just () with \v).

Reference with \1, \2, etc.

" Swap first two words
:%s/\v(\w+)\s+(\w+)/\2 \1/

" Reformat date: 2026-03-15 → 03/15/2026
:%s/\v(\d{4})-(\d{2})-(\d{2})/\2\/\3\/\1/g

" Add quotes around values
:%s/\v(\w+)\=(\S+)/\1="\2"/g

" Duplicate line content: foo → foo foo
:%s/\v^(.+)$/\1 \1/

Lesson 4: Special Replacement Tokens

Token Meaning

\0 or &

Entire match

\1 - \9

Capture group 1-9

\u

Uppercase next character

\U

Uppercase until \E

\l

Lowercase next character

\L

Lowercase until \E

\E

End case conversion

" Uppercase the match
:%s/\verror/\U&\E/g
" Result: ERROR

" Capitalize first letter of words
:%s/\v<(\w)(\w+)/\u\1\L\2/g

" UPPERCASE entire line
:%s/.*/\U&/

" lowercase entire match
:%s/ERROR/\L&/g

Lesson 5: The Global Command

Syntax: :g/pattern/command

Execute command on all lines matching pattern.

" Delete all comment lines
:g/^#/d

" Delete all blank lines
:g/^$/d

" Copy matching lines to end
:g/ERROR/t$

" Move matching lines to line 1
:g/TODO/m0

" Substitute only on matching lines
:g/DEBUG/s/old/new/g

" Execute normal mode commands
:g/pattern/normal dd

Inverse Global (:v)

" Delete lines NOT matching pattern
:v/ERROR\|WARN/d

" Keep only lines with IP addresses
:v/\v\d{1,3}\.\d{1,3}/d

Lesson 6: Lookaround in vim

vim supports lookahead/lookbehind with different syntax:

vim Syntax PCRE Equivalent

\zs

\K (start match here)

\ze

End match here

\@=

Lookahead

\@!

Negative lookahead

\@⇐

Lookbehind

\@<!

Negative lookbehind

" Match only the number after 'port='
/port=\zs\d\+
" Matches: 8080 (not 'port=8080')

" Match word before colon
/\w\+\ze:
" Matches: 'key' in 'key: value'

" Match foo only if followed by bar
/foo\(bar\)\@=
" Matches: 'foo' in 'foobar', not 'foobaz'

Practical Workflows

Refactoring Variable Names

" Rename variable in entire file
:%s/\voldVar\b/newVar/g

" Rename only in function (with visual selection)
" 1. Select function with va{
" 2. Run substitution
:'<,'>s/\voldVar\b/newVar/g

Log Cleaning

" Remove timestamps
:%s/\v^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\s*//

" Extract only ERROR lines
:v/ERROR/d

" Anonymize IPs
:%s/\v\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/X.X.X.X/g

Code Formatting

" Add trailing comma to array elements
:%s/\v^(\s+\S.*)$/\1,/

" Convert snake_case to camelCase
:%s/\v_(\w)/\u\1/g

" Add semicolons to line ends (if missing)
:%s/\v([^;{])\s*$/\1;/

Config Modifications

" Comment out a section
:g/^\[database\]/.,/^\[/s/^/# /

" Uncomment lines
:%s/^# //

" Change config values
:%s/\vdebug\s*\=\s*\w+/debug = true/

Quick Reference Card

" SEARCH
/\vpattern          " Very magic search
/pattern\c          " Case insensitive
/pattern\C          " Case sensitive

" SUBSTITUTE
:%s/old/new/g       " All occurrences, all lines
:%s/old/new/gc      " With confirmation
:5,10s/old/new/g    " Lines 5-10

" CAPTURE GROUPS (very magic)
/\v(\w+)            " Capture word
:%s/\v(\w+)/[\1]/g  " Wrap in brackets

" CASE CONVERSION
\U \L \u \l \E      " Upper/lower case

" GLOBAL COMMAND
:g/pattern/d        " Delete matching lines
:v/pattern/d        " Delete NON-matching lines
:g/TODO/t$          " Copy TODO lines to end

" LOOKAROUND
\zs                 " Start match here
\ze                 " End match here

Exercises to Complete

  1. [ ] Search for all function definitions

  2. [ ] Replace all IPs with "[REDACTED]"

  3. [ ] Swap key=value to value:key format

  4. [ ] Delete all blank lines and comments

  5. [ ] Convert ALL_CAPS to Title_Case

Self-Check

Solutions
" 1. Function definitions
/\vdef \w+\(

" 2. Redact IPs
:%s/\v\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/[REDACTED]/g

" 3. Swap key=value
:%s/\v(\w+)\=(\w+)/\2:\1/g

" 4. Delete blanks and comments
:g/^$/d
:g/^#/d
" Or combined: :g/\v^(#|$)/d

" 5. ALL_CAPS to Title_Case
:%s/\v([A-Z])([A-Z]+)/\1\L\2/g

Next Session

Session 08: Python re Module - Regex in scripts and automation.