1. Introduction

The Vi editor comes with many advanced features. While a basic one in theory, the search function, like many others, is enhanced when using vi in practice.

In this tutorial, we discuss simple and complex searching in Vi. First, we go over basic search commands and concepts. There, we cover directions, repeating searches, and offsets. Finally, we turn to advanced searching with movement operations, complex expressions, spelling, and wrap control.

For brevity, we use vi (Vi) when referencing both the Vi and Vim editors.

We tested the code in this tutorial on Debian 11 (Bullseye) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments.

2. Basic Searching in Vi

Since performing a search is often vital for editing, this function is well-supported in the Vi editor. Still, even the basic search commands have extras.

2.1. Search and Directions

Instead of a single one with modifiers, there are two separate search commands in Normal mode depending on the search direction:

Notably, either option uses the string or pattern, i.e., term, directly after the command. For example, we can perform a forward search for expression terms:

/expression terms

Isolated forward case-sensitive literal searches are perhaps the simplest and most intuitive form of the command. Let’s dive deeper.

2.2. Next Occurrence

Depending on the desired search direction, we can get to the next occurrence with either / slash or ? question mark. The former would place the cursor at the start of the match after the current one, while the latter goes to the previous match. In both cases, the last search string or pattern is used.

For instance, after positioning the cursor HERE in this sentence, a search like /in goes to the match just before “this”, while ?in goes near the end of positioning.

At this point, manually repeating the respective command alone would also have different results for the same sentence:

  • / (hotkey n) after /in would match in from search for /in in the sentence
  • ? (hotkey Shift+N) after ?in would place the cursor just before instance

Of course, we can always make the repetition automatic by entering a number just before the command.

2.3. Offset

In addition, we can add an offset to start the search at:

/expression terms/5

In this case, we begin 5 lines after the current cursor line, skipping any matches in those lines. Moreover, we can prefix with minus to start a number of lines before the current cursor line, adding to any potential matches.

Finally, we can start a number of characters before () or after (+) the [s]tart ([b]egin) or [e]nd of the last match. So, to continue a forward search 30 characters before the start of the last match, we can combine the prefixes:

//s-30

This way, we can include content that might have been skipped without manually moving the cursor.

3. Advanced Searching in Vi

Being a VersatIle editor, vi also has many advanced search features.

Let’s discuss some of them.

Actually, we can move the cursor based on character searches within the same line.

For example, t0 searches for the next 0 and places the cursor a character to the left of it. On the other hand, Fx moves over to the previous occurrence of x on the line.

In essence, the lowercase commands f and t search forward, while the uppercase F and T search backward for a character within the line.

3.2. Regular Expression (regex)

In addition to literal strings, we can employ regular expressions for searching in Vi.

Regular expressions (regex) are a way to match or capture parts of strings via a special syntax, designating rules for the match. While POSIX regular expressions are one standard, Vi has its own regular expression syntax.

For example, we can employ a regex to search for an x with or without a leading dash:

/-\?x

Interestingly, prepending \v to a regex activates the magic option, bringing the overall syntax closer to that of Perl:

/\v-?x

For brevity, we’ll use the magic regular expression mode below.

Part of regular expressions is the lookahead and lookbehind mechanism. Vi has its own syntax for that:

  • (term)@= – positive lookahead
  • (term)@! – negative lookahead
  • (term)@<= – positive lookbehind
  • (term)@<! – negative lookbehind

In essence, if we use (-)@<!x, we want to find any x without a leading dash.

3.3. Word Searches

Vi provides easy ways to find other occurrences of the word under the text or mouse cursor:

  • * – forward search for the word under the cursor
  • # – backward search for the word under the cursor
  • S+LeftMouse – forward search for the word under the mouse cursor
  • S+RightMouse – backward search for the word under the mouse cursor

These save the effort of typing out the word of interest after a search command. In fact, doing so might lead to misspellings.

3.4. Specialized Searching

With a broader definition of searching, we can consider even more commands:

  • ]s, ]S – move to the next misspelled (bad) word after the current cursor position
  • [s, [S – move to the previous misspelled (bad) word before the current cursor position

Of course, the above is far from a comprehensive list but provides an idea about the versatility of searching with Vi.

3.5. Wrapping

Since the search direction might deplete matches, Vi provides the wrapscan option. If wrapscan has its default on value, any search that reaches the TOP or BOTTOM, wraps around the other end with a message that it has done so:

search hit [TOP|BOTTOM], continuing at [BOTTOM|TOP]

With wrapscan off, the message simply becomes search hit [TOP|BOTTOM] without match.

4. Summary

In this article, we explored basic and advanced ways to search in Vi.

In conclusion, special modifiers and directions are implemented in many Vi operations since large files are a common occurrence and refining searches can save much time and resources.