Saturday, December 1, 2007

Vim Tips -- Search and Replace


Did you ever wonder if there was an easy way to send an example file for someone to look at, but still keep your private information safe?

Sure you can use a sed, or perl one-liner, as I discussed: using-bash-and-sed-to-modify-text-file.html, but why not use search and replace in vi / vim before publishing your info? That way you can see exactly what you are changing. Remember, while vim is installed by default on most Linux distros, is also available for Windows, and it is free -- http://www.vim.org

Suppose you have part of a log file, or nmap output that contains real hostnames, a real domain name, and real IP addresses. You want someone to help you troubleshoot something, but you don't what to give the real info for everyone to see.

Start with the info in a text file, such as this:

Host realhost-1.realdomain.com (192.168.0.54) appears to be up.
Host realhost-2.realdomain.com (192.168.0.55) appears to be up.
Host realhost-3.realdomain.com (192.168.0.56) appears to be up.
Host realhost-4.realdomain.com (192.168.0.57) appears to be up.
Host realhost-5.realdomain.com (192.168.0.150) appears to be up.
Host realhost-6.realdomain.com (192.168.0.151) appears to be down.

With a few quick search commands, the output can be converted to this:

Host xyz-1.example.com (10.10.10.34) appears to be up.
Host xyz-2.example.com (10.10.10.35) appears to be up.
Host xyz-3.example.com (10.10.10.36) appears to be up.
Host xyz-4.example.com (10.10.10.37) appears to be up.
Host xyz-5.example.com (10.10.10.130) appears to be up.
Host xyz-6.example.com (10.10.10.131) appears to be down.


O.K., here are the commands.

The fastest way to replace "realhost" with "xyz" on every line in the file is to use the %s command:

To enter command mode, press <esc>
:%s/realhost/xyz/g

What this means is
% = every line in the file
s = search
/realhost/ = pattern to search for
/xyz/ = text to replace with
g = global

Suppose you want to do this on almost all lines, but would like to confirm each replacement. That's easy, just use a "c" for confirm.

:%s/realhost/xyz/gc

c = confirm

O.K., but what if you only want to replace a few lines in the file? Simply use the line numbers separated by a comma instead of the "%" symbol:

:7,12s/192.168.0/10.10.10/g

Use ".", or nothing to search and replace only on the current line:

:s/5/3/gc

The items between the slashes are called regular expressions, and work as expected. When searching for special characters, e.g. "$ / ^", etc. they must be escaped by using a backslash "\" (Use \\ to get a literal backslash).

That's it. You're done, so save the file, and quit
<esc>
:wq!

Here is a list that may come in handy:

Vi / Vim Substitution and Regular Expressions Cheat Sheet


Vi / Vim Substitution and Regular Expressions
----------------------------------------------
% = every line in the file
s = search
/ / = pattern to search for
/ / = text to replace with
g = global
c = confirm each substitution
p = Print the line after the change is made

Regular Expressions (regex)
---------------------------
. = Matches any single character (including spaces), except newline.
* = Matches zero or more of the preceding single character
^ = Match at the beginning of line, used at the beginning of a regex
$ = Match at the end of the line
\ = Escape special characters
[ ] = Match any one character, e.g. [a-z] = lowercase, [^a-z] = not lowercase
\( = Save pattern
\< = Match characters at the beginning of a word

POSIX character classes
------------------------
[:alpha:] = Alphabetic characters
[:digit:] = Numeric characters
[:alnum:] = Alphanumeric characters
[:space:] = Whitespace characters
[:blank:] = Space and tab characters
[:cntrl:] = Control characters
[:upper:] = Uppercase characters
[:lower:] = Lowercase characters
[:graph:] = Printable and visible nonspace characters
[:print:] = Printable characters including whitespace
[:punct:] = Punctuation characters
[:xdigit:] = Hexadecimal characters

Metacharacters Used in Replacement Strings
-------------------------------------------
\n = Replaces with text matched by the nth pattern -- \( \)
\ = Escape special character
& = Replaced with entire text matched by the search pattern
~ = String found replaced by text of previous search
\u, \l = Change next character to upper or lowercase

No comments: