* Find and replace in vi

From Edgar BV Wiki
Jump to navigation Jump to search

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML><HEAD><TITLE>Linux.ie :: vi Tutorial 2</TITLE> <META content="text/html; charset=windows-1252" http-equiv=Content-Type> <SCRIPT language=JavaScript> // 1999 John Kelly // Use this if you want to // It's not like I worked at this. // that is all gddgNet = ""; if ((navigator.appName == "Netscape") && (navigator.appVersion.indexOf("3.") != -1 )) gddgNet = 1; if ((navigator.userAgent.indexOf("X11") != -1) && (gddgNet != 1)) document.write("<link rel='stylesheet' href='/styles/styles-x11.css'>") else if ((navigator.userAgent.indexOf("Mac") != -1) && (gddgNet != 1)) document.write("<link rel='stylesheet' href='/styles/styles-win.css'>") else if ((navigator.userAgent.indexOf("Win") != -1) && (gddgNet != 1)) document.write("<link rel='stylesheet' href='/styles/styles-win.css'>") </SCRIPT>

<META content="MSHTML 5.00.2920.0" name=GENERATOR></HEAD> <BODY bgColor=#ffffff leftMargin=0 rightMargin=0 topMargin=0 marginheight="0" marginwidth="0">

<TBODY> </TBODY>
<TBODY> </TBODY>
<IMG src="find and replace in vi_files/left.gif"> <IMG src="find and replace in vi_files/pixel.gif">        <A class=osdn href="http://cork.linux.ie/">cork.linux.ie</A>  · <A class=osdn
           href="http://galway.linux.ie/">galway.linux.ie</A>  · <A class=osdn
           href="http://www.linux.ie/stats/">stats</A>
            · <A class=osdn href="http://www.linux.ie/legal/">legal
           info</A>  · <A class=osdn
           href="http://www.linux.ie/legal/copyright.php">copyright</A>
<IMG alt="" height=1 src="find and replace in vi_files/pixel.gif" width=1> <IMG alt="" height=1 src="find and replace in vi_files/pixel.gif" width=1> <IMG alt="" height=1 src="find and replace in vi_files/pixel.gif" width=1>
<IMG alt="" height=1 src="find and replace in vi_files/pixel.gif" width=1> <IMG alt="" height=1 src="find and replace in vi_files/pixel.gif" width=1> <IMG alt="" height=1
           src="find and replace in vi_files/pixel.gif"
width=1>
<TBODY> </TBODY>
    <A href="http://www.linux.ie/"><IMG border=0 src="find and replace in vi_files/logo.gif"></A> <IMG src="find and replace in vi_files/tux.gif">
<IMG alt="" height=1 src="find and replace in vi_files/pixel.gif" width=1>

<TBODY> </TBODY>
   
<IMG alt='\"\"' border=0 src="find and replace in vi_files/grad-top.gif">
<IMG alt="" border=0 src="find and replace in vi_files/grad.gif"> <A href="http://www.linux.ie/index.php">Home</A>
<IMG alt="" border=0 src="find and replace in vi_files/grad.gif"> <A href="http://www.linux.ie/newusers/">New Users</A>
<IMG alt="" border=0 src="find and replace in vi_files/grad-sel.gif"> <A href="http://www.linux.ie/articles/">Articles</A>
<IMG alt="" border=0 src="find and replace in vi_files/grad.gif"> <A href="http://www.linux.ie/download/">Download</A>
<IMG alt="" border=0 src="find and replace in vi_files/grad.gif"> <A href="http://www.linux.ie/community/">Community</A>
<IMG alt="" border=0 src="find and replace in vi_files/grad.gif"> <A href="http://www.linux.ie/vendors/">Vendors</A>
<IMG alt='\"\"' border=0 src="find and replace in vi_files/grad-bot.gif">

 
           <FORM action=/search.php method=get> <INPUT name=words
size=10>
<INPUT name=config type=hidden value=htdig>  <INPUT type=submit value=Search></FORM>
Archives:
           <FORM action=/archiveredirect.cgi method=get><SELECT name=listname>
             <OPTION value=cork>cork@</OPTION> <OPTION selected
             value=ilug>ilug@</OPTION> <OPTION value=social>social@</OPTION>
<OPTION value=webdev>webdev@</OPTION></SELECT>
    <INPUT type=submit value=GO!> </FORM>

<A href="http://setiathome.ssl.berkeley.edu/cgi-bin/cgi?cmd=team_lookup&name=ilug">Join the
ILUG SETI
Group</A>



















  <IMG alt="" height=1 src="find and replace in vi_files/pixel.gif" width=1> <TBODY> </TBODY>
<TBODY> </TBODY>
 :: <A
                 href="http://www.linux.ie/articles/">Articles</A> :: <A
                 href="http://www.linux.ie/articles/tutorials/">Tutorials</A> ::
vi Tutorial 2

Oct 29th, 1999

Firstly, I'd like to thank everybody who mailed me about my last vi tutorial for their kind words - and for asking for more!
I also want to clarify that I am not using vi itself but the better known clone called 'vim' which has been ported to a number of different operating systems (Linux, Beos, VMS, DOS, Windows and Amiga to name but a few) and is available for download at the vim website, <A href="http://www.vim.org/">http://www.vim.org/</A>. I'm mentioning this because there is a chance that I might accidentally describe some vim specific functionality and would greatly appreciate it if corrections were emailed to me. Anyways, time to get on with it...

Lines.
There is one mildly annoying thing about vi, which is that for the most part you don't know for certain if one line of text is displayed as just one line or whether it might be so long as to wrap around and be displayed on the screen as being two or more lines. This can be extremely annoying if for example you delete four lines and, due to word wrap, you really only should have deleted two.
For this reason it would be rather nice to know where the lines end and how to do something about it.
Doing the first is quite simple - type :set list to see where the lines end (which will be indicated with dollar signs, tabs indicated with '^I') and :set nolist to get the display back to normal.
Getting vi to do something about it preemptively is rather simple too. All that you need do is type :set wrapmargin=1 to make vi force lines not to wrap, this is a really useful command which probably should be included in your .exrc file.
If for some reason you want to undo this, just type :set wrapmargin=0. You could also use :set wrap and :set nowrap for turning wordwrap on and off.

Seek and Find.
One thing that I was asked to cover was searching for text - and replacing it. On the face of it, searching for text is fairly simple. Press / then type in the text that you want found, pressing return afterwards. To find the next occurrance of the same text just press / and return again.
Using / means that the search text will be looked for further into the file that you are editing - if you want vi to search in the other direction then use the question mark (and again you can use ? followed by the return key to search for the previous occurrance of the text you are searching for).
If you are alternating between forward and reverse searches you don't have to specify the search text a second time.
For example, let's say you were looking for the word 'spam' and you accidentally hit / and the return key before you can read anything else and are shown the next occurrance of 'spam'. You don't have to type ?spam - ? on it's own will suffice. You can also use 'n' and 'N' for searching in the same direction and the alternate.
There's one particular disadvantage/annoyance about this though. If you look for the word 'to' vi will find it all over the place as a portion of longer words (try looking for 'to' in "Going towards oblivion tomorrow too!").
There are a number of ways that you can solve this problem. Once you find the first correct occurrance of the word you can use '*' to find the next occurrance of it as a whole word. (* will search forwards, # will search backwards.) What if you are nowhere near the first occurance of the whole word? To solve this you have to wrap the text you are looking for with angle brackets - which you have to 'escape' with '\'. For example, if you want VI to search for the word 'tux' and don't want the word 'tuxedos' to be found, this is what you'd type: /\<tux\> followed by the return key. This solution is the better one, mostly because you can use it to search for a phrase or a certain combination of words like "if you".
You can search for regular expressions too, just like with sed so if you need to find any number you can do /[0-9] and so on. Regular expressions are much too complex for me to write about in this tutorial, entire books have been written about them. Though of course this mightn't stop me from writing a tutorial on them later on. Don't hold your breath though!

Search and Replace.
Lets say that you need to replace a word with a different one. How would you do it?
Here's how (this also works on portions of words).
Type :s/word/replacement/ (though the last / is really needed).

That works just fine for replacing that word just once, if you need to do it a number of times you need to use the g modifier:
:s/word/replacement/g
Which is all well and good if the word you want to replace only ever occurs on the same line as the other occurrances. Fat chance of that in the real world. So how do you do that then?
What you can do is this, type :.,.+ and then a number followed by s/word/replace/g The number is taken to be the number of lines that you want the substitute command to process less one. So if I have a paragraph consisting of five lines and I want to swap 'Fred' with 'Barney' I'd use:
:.,.+4s/Fred/Barney/g
instead of moving to each line and typing :& to repeat the last substitution.
To do this to every line in the file you can either use the hard way or the easy way. I'm going to describe the hard way first - just for the sake of completeness than for any other reason.
What you need to do is this:
Go to the first line in the file (with 1G), press <ctrl-G> to get vi tell you how many lines are in the file (lets say it's 105) and then use:
:.,.+104s/Fred/Barney/g
But this is way too long-winded and is something that you'd rather not do.
The simplest way is to use:
:%s/Fred/Barney/g
You should be aware though that this moves the insertion point to where the last replacement occurred, so use := to find out which line you have the insertion point on before you do anything so you can use nG (where n is the line number) to get back to that line straight away, with out any faffing around.
That's great, but what if you want to confirm which occurances of the word are supposed to be replaced with the other word. How would you do that? Setting this up is really quite simple, you need to use the confirm modifier in conjunction with the global one (which is already there). So you'd use :.,.+Ns/word/replacement/cg where N is again the number of lines that you want affected (less/minus 1).
One particular thing that I was asked about is the annoying fact that if you edit a text file which was edited under DOS or Windows in your linux vi session there are a lot of weird ^M characters displayed. If you are using vi to edit perl scripts or HTML pages with JavaScript in them these ^M characters will cause problems. These ^M characters are called Carriage Returns. You can use the substitute command to get rid of these. Initially you might try to do this with :%s/^M//g (where N is again the number of lines) This simply won't work because the command is looking for two seperate characters, '^' and 'M'. What you need to do is this:
:%s/<ctrl-v><return>//g
What <ctrl-v> does here is tell the substitute command that the following keystroke is a part of the text to be replaced. So if you wanted remove all tab characters from the document you could use:
:%/<ctrl-v><tab>//g

You insensitive...
Bill Meyer asked me about case insensitive searches. It's very simple to do a case insensitive search & replace. All that it means is using the 'i' modifier. So to change all occurrances of both 'betty' and 'Betty' to 'Wilma' you'd use this:
:%s/betty/Wilma/gi
If though you want to change all occurrances of 'ken' and 'Ken' to Kenneth, you have to be more careful or you could have the word broken changed to broKenneth. All you have to do is wrap the word being replaced with those escaped angle brackets.
:%s/\<ken\>/Kenneth/gi

You might be tempted to try :/foo/i to find all occurrances of foo and Foo or some such variation. But you'd be wrong.
To do this use
:set ic
and then perform your search (ic being an abbreviation for 'ignore case'). If you then want to do a case sensitive search you will need to use the following:
:set noic

Abbreviations & Autocorrect
The support for abbreviations in vi is really quite handy, both for taking shortcuts (for example typing 'sw' as a word and having it replaced with the word 'software') and for correcting common spelling mistakes (replacing 'Adn' with 'And').
This is a very simple thing to do, for example
:ab sw software
tells vi that everytime I type sw as a whole word it will replace it with the word software.
Similarly I have a different abbreviation set up to replace ailug with the words "Irish Linux Users' Group":
:ab ailug Irish Linux Users' Group
You can see from this that you do not have to escape the words that the abbreviation represents.
There's just one slight problem that you might encounter - if you try to redefine an abbreviation, you'll find that the moment you get as far as specifying what the abbreviation represents, that the abbreviation itself will get expanded to the older meaning/representation. You must unabbreviate an abbreviation before you can redefine it. To do this type :una followed by the name of the abbreviation and then redefine it. You can see a list of all abbreviations that you have defined by using :ab on it's own.
Naturally you wouldn't want to type in a hoard of ab commands each time that you open a file. It makes much more sense to set up these abbreviations in a common file that vi can reference when you start it, the .exrc file (or .vimrc if you're using vim). This is a text file which can contain (amongst other things) abbreviation commands and set commands (without the colon at the start of the line).

Filters.
One nice thing about vi is that you can filter your document through an external program to replace it's text with the output of the filter.
Let me explain.
Suppose you are compiling a list of the reference books that you own (for whatever reason). For example:

	Perl Power!
	CGI Programming in C & Perl
	Information architecture for the World Wide Web
	Perl 5 Desktop Reference
	Webmaster in a nutshell
	Linux in a nutshell
	Perl Cookbook
	HTML 3.2 plus How-To
	The new hacker's dictionary (third edition)
Wouldn't it read better if it were in alphabetical order? And
           even better if you did not have to order the titles of these books
           'by hand'?
To do it you should use the following, :x,y!sort, where x is the line number where the list starts
and y is the line number where it ends. This would result with:
	CGI Programming in C & Perl
	HTML 3.2 plus How-To
	Information architecture for the World Wide Web
	Linux in a nutshell
	Perl 5 Desktop Reference
	Perl Cookbook
	Perl Power!
	The new hacker's dictionary (third edition)
	Webmaster in a nutshell
If you know the number of entries in the list and couldn't be
           bothered to specify the line numbers you can type n!!sort
           (note that the colon is missing and you should replace 'n' with the
           number of entries that you want affected).

Word Count
A better use of filters comes to mind, and that's to get a word count of the document (1752 words and counting!). To do this type:
:%!wc
This will display a group of three numbers like, "206 1765 9995" (and pretty much nothing else). These numbers indicate the number of lines, words and characters. To get the document text back press 'u'.

Finishing Off
Well that's pretty much it for now, between this tutorial and the last one you should have an idea of how to edit files in vi, how to find text, replace it and also how to use filters to sort text alphabetically and get a word count.
These are the 'essentials' that I think should be know by anybody who wants to use vi effeciently, though of course vi gurus are probably shaking their heads in disbelief saying 'he didn't cover...'.
As always, please feel free to email me with corrections and anything else that you think I ought to cover at a later stage [whether I will or not is another matter - but there's always a chance].

Special Characters source: "/usr/local" destination: "/usr/sbin"
%s/\"usr//local\"/\"/usr//sbin\"/g
so in front of special characters like html dump a "\" infront of it i.e. " = \"

The Declan clause.
This tutorial was written by <A href="mailto:root@linux.ie">Ken Guest</A>, <A href="http://technobrat.net/">http://technobrat.net/</A>.
Copyright © Ken Guest 1999.
Publication of this work in any printed or electronic form in part or in whole for non private use without (a) the inclusion of the above copyright notice (b) written permission of the author is an infringement of copyright and thus prohibited by law and international convention.

Credits
Thanks to:
<A href="mailto:bill.meyer@tellabs.spamspamspam.com">Bill Meyer</A>, <A href="mailto:john.allen@oceanfree.spamspamspam.net">John Allen</A>, <A href="mailto:robhill@indigo.spamspamspam.ie">Rob Hill</A> and <A href="mailto:tethys@it.newsint.co.spamspamspam.uk">Tethys</A> for corrections and guidance!

                                                                                                    

 
<IMG alt="" height=1 src="find and replace in vi_files/pixel.gif" width=1>
<TBODY> </TBODY>

<A href="http://www.indigo.ie/"><IMG border=0 src="find and replace in vi_files/indigopower.gif"></A>
Maintained by the ILUG <A
     href="mailto:webmaster@linux.ie">website team</A>.
Linux is a trademark of Linus Torvalds, used with permission. Networking services kindly provided by <A href="http://www.indigo.ie/">Indigo</A>.
No penguins were harmed in the production or maintenance of this
website.

</BODY></HTML>