Photo Courtesy: B Zedan
This article is part of the on-going Vi / Vim Tips and Tricks series. Vim is commonly mentioned as text editor, not text creator. Why ? Because we spend lot of time editing an existing text than creating new text. In the text editing, text/pattern substitutions becomes a vital part.
In this article, let us review how to perform both basic and advanced text and pattern substitution features in Vi and Vim Editor. These features are explained using 12 very practical and powerful text substitution examples.
Syntax of the text substitution inside vim editor:
:[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
Following are three possible flags.
- [c] Confirm each substitution.
- [g] Replace all occurrences in the line.
- [i] Ignore case for the pattern.
Example 1. Substitute all occurrences of a text with another text in the whole file
This is the basic fundamental usage of the text substitution inside Vi editor. When you want a specific text to be replaced with another text in the entire file then you can use the following sequence.
:%s/old-text/new-text/g
- %s – specifies all lines. Specifying the range as ‘%’ means do substitution in the entire file.
- g – specifies all occurrences in the line. With the ‘g’ flag , you can make the whole line to be substituted. If this ‘g’ flag is not used then only first occurrence in the line only will be substituted.
Example 2. Substitution of a text with another text within a single line
When you want a specific text to be replaced with another text within a single line in a case insensitive manner. Specifying no range means, do substitution in the current line only. With the ‘i’ flag, you can make the substitute search text to be case insensitive.
:s/I/We/gi
Example 3. Substitution of a text with another text within a range of lines
With the range, you can make only a range of line to be affected in the substitution. Specifying 1, 10 as range means, do substitution only in the lines 1 – 10.
:1,10s/helo/hello/g
Example 4. Substitution of a text with another text by visual selection of lines
You can also select a specific lines by visually selecting those lines. Press CTRL + V in command mode, use navigation keys to select the part of the file you want to be substituted. Press ‘:’ which will automatically formed as :'<,’> Then you can use the normal substitute as
:'<,'>s/helo/hello/g
Example 5. Substitution of a text with another text only the 1st X number of lines
Using count in substitution, If you specify the count N in the substitution then it means do substitution in N lines from the current position of the cursor. do substitution in 4 lines from the current line.
:s/helo/hello/g 4
Example 6. Substitute only the whole word and not partial match
Let us assume that you want to change only the whole word ‘his’ to ‘her’ in the original text mentioned below. If you do the standard substitution, apart from changing his to her, it will also change This to Ther as shown below.
Standard Subsitution
Original Text: This is his idea :s/his/her/g Translated Text: Ther is her idea
Whole Word Subsitution
Original Text: This is his idea :s/\<his\>/her/ Translated Text: This is her idea
Note:: You should enclose the word with < and > , which will force the substitution to search only for the full word and not any partial match.
Example 7. Substitute either word1 or word2 with a new word using regular expression
In the following example, it will translate any occurrences of either good or nice will be replaced with awesome.
Original Text: Linux is good. Life is nice. :%s/\(good\|nice\)/awesome/g Translated Text: Linux is awesome. Life is awesome.
You can also do substitution by specifying regular expression. Following example does the substitution of hey or hi to hai. Please note that this does not do any substitution for the words ‘they’, ‘this’.
:%s/\<\(hey\|hi\)\>/hai/g
- \< – word boundary.
- \| – “logical or” (in this case hey or hi)
Example 8. Interactive Find and Replace in Vim Editor
You can perform interactive find and replace using the ‘c’ flag in the substitute, which will ask for confirmation to do substitution or to skip it as explained below. In this example, Vim editor will do a global find the word ‘awesome’ and replace it with ‘wonderful’. But it will do the replacement only based on your input as explained below.
:%s/awesome/wonderful/gc replace with wonderful (y/n/a/q/l/^E/^Y)?
- y – Will replace the current highlighted word. After replacing it will automatically highlight the next word that matched the search pattern
- n – Will not replace the current highlighted word. But it will automatically highlight the next word that matched the search pattern
- a – Will substitute all the highlighted words that matched the search criteria automatically.
- l – This will replace only the current highlighted word and terminate the find and replace effort.
Example 9. Substituting all lines with its line number.
When the string starts with ‘\=’, it should be evaluated as an expression. Using the ‘line’ function we can get the current line number. By combining both the functionality the substitution does the line numbering of all lines.
:%s/^/\=line(".") . ". "/g
Note: This is different from the “:set number” where it will not write the line numbers into the file. But when you use this substitution you are making these line number available inside the file permanently.
Example 10. Substituting special character with its equivalent value.
Substituting the ~ with $HOME variable value.
Original Text: Current file path is ~/test/ :%s!\~!\= expand($HOME)!g Translated Text: Current file path is /home/ramesh/test/
You can use expand function to use all available predefined and user defined variables.
Example 11. Alter sequence number in a numbered list while inserting a new item
Assume that you have a numbered list like the following inside a text file. In this example, let us assume that you want to add a new line after Article 2. For this, you should change the number of all other articles accordingly.
vi / vim tips & tricks series Article 1: Vi and Vim Editor: 3 Steps To Enable Thesaurus Option Article 2: Vim Autocommand: 3 Steps to Add Custom Header To Your File Article 3: 5 Awesome Examples For Automatic Word Completion Using Ctrl-X Article 4: Vi and Vim Macro Tutorial: How To Record and Play Article 5: Tutorial: Make Vim as Your C/C++ IDE Using c.vim Plugin Article 6: How To Add Bookmarks Inside Vim Editor Article 7: Make Vim as Your Bash-IDE Using bash-support Plugin Article 8: 3 Powerful Musketeers Of Vim Editor ? Macro, Mark and Map Article 9: 8 Essential Vim Editor Navigation Fundamentals Article 10: Vim Editor: How to Correct Spelling Mistakes Automatically Article 11: Transfer the Power of Vim Editor to Thunderbird for Email Article 12: Convert Vim Editor to Beautiful Source Code Browser
3rd Article “Make Vim as Your Perl IDE Using perl-support.vim Plugin” got missed. So when you want
to add it, then you want to change “Article 3” to “Article 4”, “Article 4” to “Article 5”, upto “Article 12” to “Article 13”.
This can be achieved by the following vim substitution command.
:4,$s/\d\+/\=submatch(0) + 1/
- Range: 4,$ – 4th line to last line.
- Pattern to Search – \d\+ – digits sequence
- Pattern to Replace – \=submatch(0) + 1 – gets the matched pattern and adds 1 to it.
- Flag – as there is no flag, by default it substitutes only the first occurrence.
After executing the substitute statement the file will become like this, where you can
add the 3rd Article.
vi / vim tips & tricks series Article 1: Vi and Vim Editor: 3 Steps To Enable Thesaurus Option Article 2: Vim Autocommand: 3 Steps to Add Custom Header To Your File Article 4: 5 Awesome Examples For Automatic Word Completion Using Ctrl-X Article 5: Vi and Vim Macro Tutorial: How To Record and Play Article 6: Tutorial: Make Vim as Your C/C++ IDE Using c.vim Plugin Article 7: How To Add Bookmarks Inside Vim Editor Article 8: Make Vim as Your Bash-IDE Using bash-support Plugin Article 9: 3 Powerful Musketeers Of Vim Editor ? Macro, Mark and Map Article 10: 8 Essential Vim Editor Navigation Fundamentals Article 11: Vim Editor: How to Correct Spelling Mistakes Automatically Article 12: Transfer the Power of Vim Editor to Thunderbird for Email Article 13: Convert Vim Editor to Beautiful Source Code Browser
Note: Check the substitution changed the 3 to 4, 4 to 5 and so on. Now we can add a new line mentioning it as Article 3, and no need to do any manual changes.
Example 12. Substituting the sentence beginnings with upper case. ( i.e title case the entire document ).
While formatting a document, making the title case is also an important thing. It can be done easily with substitution.
:%s/\.\s*\w/\=toupper(submatch(0))/g
- \.\s*\w – Search Pattern – literal . ( dot ) followed by Zero or more space, and a word character.
- toupper – converts the given text to upper case.
- submatch(0) – returns the matched pattern.
Text before substitution:
Lot of vi/vim tips and tricks are available at thegeekstuff.com. reading these articles will make you very productive. following activities can be done very easily using vim editor. a. source code walk through, b. record and play command executions, c. making the vim editor as ide for several languages, d. and several other @ vi/vim tips & tricks.
Text after substitution (Changes are in bold)
Lot of vi/vim tips and tricks are available at thegeekstuff.com. Reading these articles will make you very productive. Following activities can be done very easily using vim editor. a. Source code walk through, b. Record and play command executions, c. Making the vim editor as ide for several languages, d. And several other @ vi/vim tips & tricks.
Recommended Reading
Vim 101 Hacks, by Ramesh Natarajan. I’m a command-line junkie. So, naturally I’m a huge fan of Vi and Vim editors. Several years back, when I wrote lot of C code on Linux, I used to read all available Vim editor tips and tricks. Based on my Vim editor experience, I’ve written Vim 101 Hacks eBook that contains 101 practical examples on various advanced Vim features that will make you fast and productive in the Vim editor. Even if you’ve been using Vi and Vim Editors for several years and have not read this book, please do yourself a favor and read this book. You’ll be amazed with the capabilities of Vim editor.
Awesome Vim Editor Articles
Following are few awesome Vi / Vim editor tutorials that you might find helpful.
- Vi and Vim Macro Tutorial: How To Record and Play
- Turbocharge Firefox Browser With Vim Editor Functionality Using Vimperator Add-on
- Tutorial: Make Vim as Your C/C++ IDE Using c.vim Plugin
- Convert Vim Editor to Beautiful Source Code Browser for Any Programming Language
Note: Please subscribe to The Geek Stuff and don’t miss any future Vi and Vim editor tips and tricks.
Comments on this entry are closed.
Thanks for these great examples.
I am a :g kind of vi guy
I’m ad-hoc vim user, somehow tend to do develompent under more resource consuming/less flexxible but bit more intuitive editors but this article is another great eye opener. Keep them comming…
Don’t forget \v for very-magic mode so you don’t have to escape everything.
ie., s/\(hello\|hai\)/hi/ becomes s/\v(hello|hai)/hi/g
@housetier,
We are glad you found this article helpful. Thanks for the comment.
@Chris,
How do you use :g for substitute? One of the example I can think of would be the following:
@m,
Yeah. One of our goal is to educate everybody on the power of Vim Editor. I’m glad you found this article as an eyeopener to start using the Vim editor intensively.
@Shawn,
Awesome tip. Thanks for the great tip about the \v , which escapes everything. So, example 7 in this article can be written as:
using :g to do a substitute is as follows
:g/xyz/s//abc/
This substitutes the first occurance of xyz with abc on every line
:g/xyz/s//abc/g
This substitutes all occurances of xyz with abc.
i like it. thanks
@Chris,
Thanks for explaining how you use the :g for substitution in vim.
@Behrad,
Thanks for the comments. I’m really glad that you liked this article and found it useful.
Hi Ramesh,
NIce article! I have a question though.
In the examples provided above, I would like to take the following example for my question:
:s/I/We/gi
So in the above command any occurrence of I or i will be replaced with We. But this can also affect words like Ignore, classic, and so on where we have occurrence of either I or i.
Is there any method that we can use to find a replace the strings occuring at a certain given position in the word? Like if we want to change the string occuring only in the first palce of a word and so on..
@Gagan,
Yes, there are methods such as:
1. Replace only words, not substrings. ( this is already explained Example 6. )
2. Replace only if “I” occurs in the first position of the word
3. Replace only if “I” occurs in a specific position of the word ( 6th position )
Hi,
I m trying to find (similar) and replace (distinct) few strings in 140 files.
request you to help me on this
definitely, we can help you. Kindly provide some more details about your requirement, and example if possible.
What if I want to replace not the first occurrence, but the second one? E.g. lines are like this:
command file1.inp >& file.inp
command file1.inp >& file.inp
Is there a way to substitute the second “inp” in each line to “out”?
Sorry, while at it, I have a second question, a follow up to a great tip #11.
Is there a way to renumber columns consecutively, no matter what the numbers are there, i.e.
Article 5: Vi and Vim Editor: 3 Steps To Enable Thesaurus Option
Article 1: Vim Autocommand: 3 Steps to Add Custom Header To Your File
Article 11: 5 Awesome Examples For Automatic Word Completion Using Ctrl-X
Article 114: Vi and Vim Macro Tutorial: How To Record and Play
Article 2: Tutorial: Make Vim as Your C/C++ IDE Using c.vim Plugi
How to make it into 1,2,3,4, etc. This would require some built in match counter I guess…
thanks for good info.
@Visvaldas
There is more than one way to do it.
1. What if I want to replace not the first occurrence, but the second one ?
Way 1: According to the example given, following is the very simplest way.
%s/inp$/out/
inp$ specifies the inp present at the end of the line ($) should be substituted.
Way 2: If you wanted a particular occurrence to be substituted then use the “Interactive find and replace” explained in Example 8.
2. Renumber columns consecutively
Simplest way is to write a macro for it as:
Step 1: Make the 1st line as 1.
Article 1: Vi and Vim Editor: 3 Steps To Enable Thesaurus Option
Article 1: Vim Autocommand: 3 Steps to Add Custom Header To Your File
Article 11: 5 Awesome Examples For Automatic Word Completion Using Ctrl-X
Article 114: Vi and Vim Macro Tutorial: How To Record and Play
Article 2: Tutorial: Make Vim as Your C/C++ IDE Using c.vim Plugi
Step 2: Place the cursor in 1, and Start recording the macro as qa
Step 3: Copy the current number ( 1 ) to the register as “ayw
Step 4: Go to the next line as j
Step 5: Change word using dw
Step 6: Paste the word from register as “aP
Step 7: Increment the current number as press CTRL + A
Step 8: Stop recording the macro as q.
Use the above macro @q to change the number for all the articles. Refer our earlier article for more clarification in macros Vi and Vim Macro Tutorial: How To Record and Play
Do we have any possibility to replace any character in a particular position with the replace chracter. For ex:
1: #!/usr/local/bin/perl
2: $resultstring = “”;
3: print(“Enter your input – type an empty line to quit\n”);
4: $input = ;
5: chop ($input);
6: while ($input ne “”) {
7: $resultstring .= $input;
8: $input = ;
9: chop ($input);
10: }
11: print (“Here is the final string:\n”);
12: print (“$resultstring\n”);
In the above program copied from a e-book I wanna replace the numbers with null in the first 3 positions.
Regards,
Arun Venky
@Arun
We can match any character by using . ( dot ) in the pattern.
%s/\v^.{3}//g
. – match any character
{3} – 3 characters.
You may want to replace the first four characters when the number of lines of code crosses 100, at that time you can use range of lines mentioned in example 3.
Thanks for this very useful question.
Sathiya Moorthy,
Thanks for your kind reply,
I have two more questions.
1.How to search and replace any character in a multiple lines but not in a range.For example in the previous program I submitted if I wanted to replace the word input in only 5th and the 7th line but not in 6 line. Because, if I understood right the pattern
5,7s/input/output/g
would replace the word input in all the 3 lines (5,6&7). How to ignore the 6th line here.
2. If I use the option “c” at the end how to control/escape any particular line without replacing the particular instance.
Again thanks for your reply,
Regards,
Arun
@Arun
1. range
Sorry as specified in the syntax of the substitute in the introduction part of this article, it is range and not multiple lines. So you cannot do some thing as you asked in a straight away manner. You can give only ranges in the first part of the substitute command.
So you can do some of the following work around to achieve, such as giving the lines in the range one by one as :5s/// and the :7s/// or using the c option.
2. c option
How to escape without replacing ?!
It is been explained in the Example #8.
Sathiya,
Thanks for the reply. I definitely gained some knowledge through this discussion.
How can I replace a full line or syntax after a certain match example:-
next_hop: 1.1.1.1
next_hop: 2.2.2.2
next_hop: 3.3.3.1
replace all with
next_hop: 1.2.3.4
Tks,
Patrick.
After playing around I can do it via the following, by replacing next_hop + >15 characters to next-hop 1.2.3.4
:g/^next_hop……………/s//next-hop 1.2.3.4/g
if you type the following it will work
:g/.\..\..\../s//1.2.3.4/
this will change all three lines to next_hop: 1.2.3.4
of course since he wants them all the same this would also work
:g/^.*$/s//next_hop: 1.2.3.4/
this would also work
:g/:.*$/s//: 1.2.3.4/
I hope that helped.
-Chris
I want to search and replace a string, however the problem is I don’t want to replace the first and the last occurances. Is there a way to do this?
I was thing of looping the search with a (<…) option is %s command. It seemed a little weird to do it this way.
Your help would be greatly appreciated.
-Srivats
Ramesh, Thanks for the useful article. However, I am trying to do the below in a file that contains several lines, some lines start with digits. I want to replace a specific char in lines that begin with a digit but not the other lines
sample text:
123this is a sample line with some characters beginning with digits
command:
:g/^[0-9]/s/[g]/G/g
doesn’t seem to work, ie, I am trying to upper case only letter g with G and only in lines that begin with a digit, any ideas?.
i want make changes in line number “1,3,4,5,6” but not in line number “2”
@Prashant
It can be done with “c” option, where you can omit substitutions on the go.
It is explained in example:8.
@ Arun
Thanks but it will do interactive manner.
But I want do it automatically.
I think that is not possible 🙁
Worked for me. thx
Thanks for the detailed tutorial. I love “thegeekstuff” now. — Pothi
Thanks, worked for me.
I would like to perform a global substitution in vi joining all lines to the previous line.
@Lou: Try this
sed ‘N;s/\n/ /’
how can i replace 123456
to 1234.56
:g/123456/s//1234\.56/
fe20.story.media. Dest:ra3-main
es135.msg. Dest:ra3-main.dns
scheduler2. Dest:ra1-main.
I need all the Dest should come in uniform say
fe20.story.media. Dest:ra3-main
es135.msg. Dest:ra3-main
scheduler2. Dest:ra1-main
:g/main.*$/s//main/
How do you do global find and replace within more than 1 file, e.g. substitute Tom with Jerry within all files in a given directory?
@Gregory: find . -type f -name * | xargs perl -pi.bak -e ‘s///g’
This is a perl command to find the files that you need to search and replace text. Infact it creates .bak for backup.
i want o find a pattern and replace it
for ex:- line 1 1234,9876540
line 2 56789000,987654012
In above example i want to replace 1234, and 56789000, with
So the output should be
line 1 9876540
line 2 987654012
Basically i want to find the pattern that stars with and ends with , and replace it with
Please help
i want o find a pattern and replace it
for ex:- line 1 pnonenumber1234,9876540pnonenumberq
line 2 pnonenumber56789000,987654012
In above example i want to replace pnonenumber1234, and pnonenumber56789000, with pnonenumber.
So the output should be
line 1 pnonenumber9876540pnonenumberq
line 2 pnonenumber987654012pnonenumberq
Basically i want to find the pattern that stars with pnonenumber and ends with , and replace it with
Please help
@Krunal,
Try this
:%s/^.*,//g
I’m giving this with the assumption the line1..line n is not present in the file.
@Arun
Thanks a ton it worked 🙂
@Arun
Thanks a ton. it worked 🙂
@Krunal
You are welcome 🙂
Awesome tips. One question though.
I have one file, which contains,say, 100 lines (big file). Then I have another file which contains 100 names (list file).
Now, I need to search for a keyword in the big file and if keyword is found, then replace it with a name from the list file and so on. Any clue on how to do this would be appreciated.
@Varun:
Elucidate your query in detail, if possible with example. As this cannot be done with Vi as such, but can be done in shell/perl, etc….
Hi
My file is having more than 1000 lines.In this i need to change the values with the same value added with another value.The example is given below,
The file is as below
ABCD#NAME001
ABCD#NAME002
ABCD#NAME0032
ABCD#NAME00454
ABCD#NAME00543
This has to changed as below,
ABCD#NAME001 Myage 30
ABCD#NAME002 Myage 30
ABCD#NAME0032 Myage 30
ABCD#NAME00454 Myage 30
ABCD#NAME00543 Myage 30
@Bala:
Try this
:%s/$/ Myage 30/
Hi, can you help.
Got 1000 lines like so:
23456234623,23645641,A TROT ,DEC 112.34
23423452345,34533313,A FLOP ,JAN 111.99
23452345343,22345512,A RIVE ,FEB 104.22
Need a comma before the final value, so it all lines come out like;
23456234623,23645641,A TROT ,DEC ,112.34
So, crux/question is, how to insert a comma into position 42 on all lines..
Thanks a lot, Paul..
@Paul:
Come out of vi and execute from prompt. In fact it is 32 position 🙂
Try this:
sed ‘s/./,/32’ file1 > file2; mv file2 file1
@Arun.
Tanks a lot Arun, but I should’ve said, I’m on WinVi, so was trying to keep it internal ; )
Do you think it’s possible keeping it within Vi? Cheers again, Paul…
@Paul:
Unfortunately there is no method to replace a particular position using vi 🙁
@ Arun
Thanks anyways, will get onto building the VM ; )
Much appreciated.. Paul
Am I wrong in thinking that if you do:
:%s/\([0-9,*][A-Z, *]\) \([0-9\.*]\)/\1 ,\2
it’ll add the comma before the final number
23456234623,23645641,A TROT ,DEC ,112.34
|———————[0-9,*][A-Z, *]———–| [0-9\.*]
I’m not at home with a linux box to test it on, but I think it’ll work 🙂
————————–dave
Hi all.
I have a huge text file (40000 lines) with names and birthdate of personalities, sorted by name.
Those I know are preceded by *. But if I insert new names, I lose my sort. I would like to move the * at the end of each line srarting with a *, so I can insert new names and then, sort my file. Finally, I want to move the * again at the start of the lines.
Actually, it’s a right shift, a sort and a left shift.
Let’s assume I have this
Adams Ryan 05-11-1974
*Adams Scott 08-06-1957
Adams Timothy 04-08-1967
*Adamson Chuck 11-06-1936
Adamson Joy 20-01-1910
And I want this
Adams Ryan 05-11-1974
Adams Scott 08-06-1957*
Adams Timothy 04-08-1967
Adamson Chuck 11-06-1936*
Adamson Joy 20-01-1910
Can vi do the global search and replace of the * ?
TIA
Pierre
@Pierre:
Try to use this, I tried this on the given sample and it worked fine.
:%s/\*.*$/&\*/ –> This is used to append * at the end for the lines starting with *
:%s/\*// –> This is to remove the * in the beginning of the line
Cheers,
Arun
Thanks Arun, it works fine. 🙂
Now last question : after I have inserted and sorted new lines, how do I remove the * at the end to put it back in the beginning ?
I have tried with some strings like yours but I got an error message.
Here we go 🙂
:%s/.*\*$/\*&/
:%s/\*$//
@dave
I tried your solution but failed, please try and let us all know the results. I’m equally eager to know how the pattern match works !!
I’m away from home this week and don’t have vi/vim on my friend’s computer, he’s a windows/ no vim guy 🙂
But the pattern match should work:
the first part \([0-9,*] should do all the numbers and commas up to ‘A’
the second [A-Z, *]\) should do all the upper-case letters, spaces and comma
then \([0-9\.*]\) should do the final numbers
then /\1 ,\2 should print the first part \(…\) a space a comma
then the second part \(…\)
Looking at it again — maybe the space at the end isn’t necessary, but it should still work 🙂
Pierre’s question could also be done as
:g/^\*/s/$/*/ ——- I don’t think the second ‘*’ has to be escaped.
as an aside, Pierre why not just leave the ‘*’ at the end of the line? 🙂
I had a similar list and I did upper-case for known and lower-case for unknown, then of course you have to do a case-agnostic sort. Just a thought. Have fun ——-dave
Thanks Arun, it works fine. But I’m a little confused because I want to understand the way it works.
A dot is supposed to match one character and a star zero or more of the previous character. What is the meaning of the dot in :%s/.*\*$/\*&/
And why is the & not at the same place in the 2 strings ?
@David, a * in the beginning of the line is easier to see because the lines have a variable number of characters.
Pierre, sorry, what I meant was just leave the ‘*’ at the end of the line, and just remove, sort then replace the first ‘*’. You remove the first one and you still have the last one to find those lines again to replace ‘*’ at the start. Sorry I probably wasn’t very clear.
I’m sure Arun will explain the other question, but here’s my answer:
:%s/.*\*$/\*&/
the dot means any character, the star means zero or more of any character, basically a
line with something on it, in this case a line with something ending in ‘*’, $ meaning the end of the line.
The ‘&’ means the previous pattern (the line) with ‘*’ in front of it.
Arun says:
:%s/\*.*$/&\*/ –> This is used to append * at the end for the lines starting with *
This means basically any line starting with ‘*’, then take that line and add ‘*’ at the end. So add ‘*’ — *\& — at start of line
— &\* — at end of line
Hope I made that clear, it’s so easy to write something that seems clear to you and of course it’s not to everyone else 🙂 have fun ———————-dave
@Pierre: Dave had already mentioned all I’m supposed to explain. Nevertheless, to put it simpler “&” –> holds the actual searched value
So while replacing I used “&” before the * for the first iteration and “&” after the * for appending * in the beginning of the line in the second iteration.
@Dave: Thanks for the support and btw the method given by you still doesn’t work for me 🙁 perhaps would need your help once you reach your linux
well Arun I finally got back home to my computer with Vim on it so I can test what I suggested and ……you’re right it didn’t work. I think I forgot how “greedy” RE’s can be. But it did give me time to think about it and I came up with these solutions:
:%s/\(\d{11},\)\(\d{8},\)\([A-Z ,]* \([0-9\.]*\)/\1\2\3 ,\4
:%s/\([0-9,]*\)\([A-Z, ]*\) \([0-9\.]*\)\1\2 ,\3
:%s/……$/,&/
:%s/[0-9,]*[A-Z ,]*/&,/
:%s/.\{6}$/,&/
:%s/^.\{33}/&,/
:%s/ / ,/g then you have to do :%s/ ,/ / twice
Hopefully I transcribed those correctly 🙂
have fun checking these out and happy holidays —————david
Thanks David for your efforts 🙂
I will try and reply you back soon!
thanks Arun, I forgot to add the best solution I found duh!
:%s/.* /&,/
————-dave
@dave; This is amazing, but wondering how it works…
Could you please explain.
Thanks,
which one? 🙂 I’ll explain the last one:
:%s/.* /&,/
this uses RE greediness to work. /.* / — dot, star, space pushes the pattern – anything followed by a space all the way to the last space
23456234623,23645641,A TROT ,DEC 112.34
^
It doesn’t stop at the first or second space because there’s another one, the third and last one – the one we want (greediness). If there was another space followed by something after the final digits this wouldn’t work. (most of the other solutions would)
/&,/ of course replaces the pattern with the pattern plus ‘,’
all the best ——————david
the up arrow didn’t finish up where I put it – it should be under the ‘1’ after DEC
——-david
This is great, I appreciate your efforts for taking time tn explain me.
Thanks a lot,
Arun
awesome stuff,,,,,,,,Thanks a lot,,,,,
How can I remove @ entirely throughout the file? I can remove ^M using
:%s/^M//g
by pressing ctrl+v then ctrl+m but ctrl+@ produces ^@.
Thanks!
did you try:
:%s/@//g ???
you don’t need ctrl+@, @ is just an ascii character.
—————-dave
I want to write a regex to match all the alphabetic characters in a file except the ones enclosed within single quotes (‘). Is there a simple and elegant way to get this done?
How can i replace a particual appearance of a special character in a line in VI editor with another character
eg:
160|PS: 30|kw-3840+lowepro||s|b|8718588399|BBY01-434822007360|1
The line has ‘ | ‘ as the delimiter. But i dont want the 3rd,4th,5th and 6th appearance of ‘ | ‘ as it is not meant to be there. How can it be replaced with ‘ + ‘ or any other character?
Omkar February 26, 2012 at 5:41 am
How can i replace a particual appearance of a special character in a line in VI editor with another character
160|PS: 30|kw-3840+lowepro||s|b|8718588399|BBY01-434822007360|1
The line has ‘ | ‘ as the delimiter. But i dont want the 3rd,4th,5th and 6th appearance of ‘ | ‘ as it is not meant to be there. How can it be replaced with ‘ + ‘ or any other character?
Try:
:%s/\(.*lowepro\)||\(\a\+\)|\(\a\+\)|\(.*\)/\1++\2+\3+\4/
this should work if the example you give is consistant ie lowepro is always there and
the letters between the ‘|’ are always letters, and there are always one or more of them. Shouldn’t be to hard to tweak if that’s not the case.
Thanks David! This works only for ‘lowepro’
But, what if the ‘lowepro’ is not there?
The pattern of ‘ | ‘ is same.
i.e in a line we will always have four ‘ | ‘ as delimiters. We need to keep the first two and the last two and replace all in the middle.
Sample of a correct record and a bad record:
Correct Record:
160|PS: 30|kw-3855|BBY01-434795143499|13
Bad Record:
160|PS: 30|kw-3840lowepro||s|p|8718588639|BBY01-434787144198|8
Also let me know is replacing the delimiter possible from outside the file? We know the line numbers where the bad records are present.
hi omkar, sorry I just took the easy way out 🙂
try
:%s/\([^|]*\)|\([^|]*\)|\([^|]*\)||\([^|]*\)|\([^|]*\)|\(.*\)/\1|\2|\3++\4+\5+\6/
good grief that looks awful, but should work on the 3,4,5 and 6 iteration of ‘|’
You can put the command into a file and call that file from ex eg
ex -s “list-file” < "command file"
you don't need to know the line numbers of "bad" records
:g/.*lowepro*/s/
should run the command on lines with lowepro
hope that helps —————david
hmmm…. looks like I was in to much of a hurry there and missed something: I was going to write:
:g/.*lowepro*/s/\([^|]*\)|\([^|]*\)|\([^|]*\)||\([^|]*\)|\([^|]*\)|\(.*\)/\1|\2|\3++\4+\5+\6/
———————–david
Thanks David! It works like magic 🙂
Thanks.. It was very very useful for me 🙂
FYI , there is a short form for TIP 12
:%s/\.\s*\w/\=toupper(submatch(0))/g can be changed to
:%s/\.\s*\w/\U&/g
“\U” means it converts all characters to uppercase after this special command.
Moreover, you can change to lower case by “\L”
example
———
:%s/\.\s*\w/\L&/g
Hi, I wonder if there is a way to substitute %f into %d
Thanks in advance
H Carlos,
Try this
:%s/\%f/\%d/g
Hi,
How can I use “J” to jon lines inside vim editor, without doing it manually.
For example I have a file which has lets say 100 lines.
I want to join the first 5 lines into 1st line. Then join next 5 lines into 2nd line, then join next 5 lines into 3rd line.
Vivek.
VIvek,
If you want to join every 5 lines into one line, try this
cat | paste – – – –
this will just write it on the screen. You may want to redirect to another file and move it to orginal file to save permanently.
Arun V
Thanks Arun. I tried this
cat playcheckpr33 |paste —–
It gives me
paste: unrecognized option `—–‘
What is the option you are using right after paste command?
Vivek.
Vivek,
I think the auto correct option has changed the hyphens to line. It is just 5 hyphens(-).
“cat playcheckpr33 |paste – – – – – ”
Arun
Arun, I did try 5 hyphens
cat | paste hyphen hyphen hyphen hyphen hyphen ( no spaces between hyphens)
It gives me error
paste: unrecognized option
Vivek.
Arun, actually i got it. There are spaces betwen hyphens.
Thanks for the tip. It works.
I have another question.
If I want random number of lines to joined together.
For example:
first 5 lines into line 1.
next 4 lines into line 2.
next 6 lines into line 3.
next 3 lines into line 4.
Vivek.
Hi,
Is there a equivalent of paste inside vi editor?
Vivek.
Vivek,
I think awk or sed should do the job. May be any other vi experts in this forum should throw comments.
Cheers,
Arun V
Can we do auto complete(By pressing tab key) for old-text . Some times it is pain to type whole word
Hi,
I am trying to invoke TL1 commands from my shell script.
Does anyone know how I can do this?
Any help would be highly appreciated.
Vivek.
re: Viveks question on joining lines in vim
try a macro
a macro ‘b’ qb4Jjq q starts the macro ‘b’ 4J join the next 4 lines and j moves to next line and q finishes the macro.
Then run 20@b which will repeat the macro 20 times
———————david
Hi David, Thanks for the tip. I really appreciate it. Since I dont think I have used macros before, is there anyway I can put them a in shell script or may be run them inside the “vi” editor in the file.
Please let me know.
Vivek.
Hi,
I have a file with dates in mm/dd/yy format. I want to replace the date. how do I do it.
For example: I have a date 09/09/2012 that occurs multiple times in the file and I want to replace this date with 05/03/2012. How do I do it? Please help.
:g, 09/09/2012,s,,05/03/2012,g
Please help with following :I need change one line list from netgroup , to column
like
1
2
3
4
Jerry,
Please be more clear on your requirement, I shall try to help you if I can.
Arun
HI ;
just asking how to search date if the files contains
2007/09/04 08:48:51 VCS NOTICE V-16-1-11022 VCS engine (had) started
2007/09/04 08:48:51 VCS NOTICE V-16-1-11050 VCS engine version=4.1
2007/09/04 08:48:51 VCS NOTICE V-16-1-11051 VCS engine join version=4.1000
2007/09/04 08:48:51 VCS NOTICE V-16-1-11052 VCS engine pstamp=4.1 03/03/05-14:58:00
2007/09/04 08:48:51 VCS NOTICE V-16-1-10114 Opening GAB library
2007/09/04 08:48:51 VCS NOTICE V-16-1-10619 ‘HAD’ starting on: stvsduxrac014
2007/09/04 08:48:52 VCS INFO V-16-1-10125 GAB timeout set to 15000 ms
2007/09/04 08:48:52 VCS ERROR V-16-1-10116 GabHandle::open failed errno =
example I need to search date 2012/11/10
what i did is /2012\/\11 — but not working.
rohaizad, you added one extra ‘\’. Try :/2012\/11 ———-david
re. Vivek’s question from way back in May, how to join every four lines into one line.
I finally came up with an Ex solution:
First put a blank line every 4th line:
:%s/\(.*\n\)\{4}/&\r this makes a pattern of 4 lines then repeats that plus a return
Then join the lines using the blank line as the delimiter
:g/./,/^$/j
Vivek you can put these lines into a file and run them against your target file.
hope it was worth the wait 🙂 ——————david
I have a file that has about 250 lines and I need to append the following text using the vi editor.
/flo_dev/DEV
Can anyone help me with the needed command.
Thanks
:g,$,s,, /flo_dev/DEV,
Awesome tips… Really useful…
thank you very much….
shinod
how bout if i want to change certain string with string in other files. for example:
first file is: /home/bee/a.txt :
db.somedatabase.update({“number”:”$i”,”status”:”1″ }, {$set:{“status”:”0″,”unsub_channel”:”Disable by ADMIN”}}, false, true);
db.somedatabase.update({“number”:”$i”,”status”:”1″ }, {$set:{“status”:”0″,”unsub_channel”:”Disable by ADMIN”}}, false, true);
db.somedatabase.update({“number”:”$i”,”status”:”1″ }, {$set:{“status”:”0″,”unsub_channel”:”Disable by ADMIN”}}, false, true);
…..and go on until 6500+ lines
second file is: /home/foo/number.txt :
12345
54321
6789
9876
…. and go on until 6500+ lines
both files have EXACT lines.
so i want to change the character “$i” (without quotation mark) at /home/bee/a.txt with the numbers on /home/foo/number.txt
can i do this with replacing commands on vim??
thanks a lot
I have a file with the following contents can i do it in vi
1
1
1
1
1
1
I want to change this to
1
2
3
4
5
6
Hi Gopal,
I don’t know if this is possible in traditional vi, but in Vim you can follow this:
: let i=1 | g/1/s//\=i/ | let i = i+1
Cheers,
Arun V
in reply to bee:
you can do what you want to do in vim, but it’s not quite as easy as a
“s/$i//
do a “man join” to learn about the join utility. This will show you how to join the 2 files into
string1
number1
string2
number2 etc etc
then you need to do a macro to do what you want:
qa start macro a
^ go to start of line
f$ finds the first $
2x removes $i
h back one character
mx mark position x
+ down to start of next line
dw delete ‘word’ actually the number
`x go to x (that’s a backslash)
p put last deletion
+ down to start of next line
dd delete line
@a repeat this macro (recursive)
q end macro
Hope this is what you want ————————david
re: bee
damn my previous post got somewhat mangled 🙂
so here is the macro just to preclude any confusion
qa^f$2xhmx+dw`xp+dd@aq
hopefully that’s more understandable 🙂 ———-david
re bee
after re-reading the join man page I must say that it may be the least-understandable
man page ever!
Do this instead
paste -d”\n” stringfile numberfile > combinedfile
Sorry about that 🙂
And obviously to run the macro ‘a’ , just do @a – but you knew that
——————-david
@david:
I was expecting your reply for bee and definitely it’s a good learning for me 🙂
Thanks,
Arun V
Arun, you are more than welcome. I also learn a lot from these questions :-). It keeps my old brain working. ——–david
Hi Everyone,
I need some help badly.
I have some thousands of lines of that might contain some or all of the following:
G03 X1.2345 Y1.2345 Z1.12345 I1.2345 J1.2345
I would like to be able to search my file and Remove the “Z1.2345”, but only if the line contains a G02 or G03.
Even if I could just search for any line that contained G02 or G03 and a Z that would
be extremely helpful!
I am very new to VIM and don’t even come close to qualifying as a programmer. lol
Thanks so much
Randy
Please, I have text file like this:
teqc +C2 -tr d -week pppp gybu201211010000a.dat > igle0000.13o
teqc +C2 -tr d -week pppp gybu201211020000a.dat > igle0000.13o
teqc +C2 -tr d -week pppp gybu201211030000a.dat > igle0000.13o
.
.
.
and so on
I want to change
Ex
teqc +C2 -tr d -week 1721 gybu201211010000a.dat > igle0001.13o
teqc +C2 -tr d -week 1721 gybu201211020000a.dat > igle0002.13o
teqc +C2 -tr d -week 1721 gybu201211030000a.dat > igle0003.13o
.
.
.
Thank a lot
Pyae
Pyae –
:%s/pppp/1721/
should replace pppp with 1721 on every line.
The incrementing number at the end of the line could be trickier! Is the “.13a” consistant through the file? Or does it change? If consistant then remove it, do the addition, then replace it. A couple of posts up is a great example of incrementing numbers – read it. If “.13a” is not a consistant suffix then you’ll have to use a macro. Also a good example of a macro is a few posts back ( from me 🙂 )
Randy – you don’t have to be a programmer to use Vim/vi, though you do have to RTFM 🙂
To find every line starting with G02 or G03 do
:g/^G0[23]/
to remove the Z etc etc you have a couple of choices
:s/Z\….. //
the first dot is escaped so it stands for a dot, the other dots stand for any digit/letter etc then a space ( or it would leave two spaces when deleting Z etc )
That depends on their being 4 numbers after Z.
If that’s not always the case then use back references:
Sample of which are also above 🙂 Have fun ———-david
Hiii Arun , I need your help
I want to know that how can I replace a string to another string in 100 places only in vi editor.
Please help me.
Hi Tapas,
Could you please be more specific on your question like how many times the same text might appear on a line. Since vi works with line numbers I doubt if the substitutions can be restricted with certain number of times.
however, if you know that there’ll be only one occurrence of the text that you search will present in a line then you can try this
:s/searchtext/replacetext/ numeber of times
The above example will replace the first occurence of a text in a line 100 times.
************
Probably writing a macro should help in replacing text at only 100 places, that I’m working on, will get back to you once I get the solution
– Arun
As Arun states a simple (very) macro will do the job:
qa – starts recording macro ‘a’
/PATTERN -search for PATTERN, the cursor stops on the first instance
cw – change word, will delete the word and put you in ‘insert’ mode
NEW PATTERN – whatever you write and exit ‘insert’ mode
q – ends recording the macro
Now just run macro ‘a’ however many times you want
eg: 100@a
will replace the first 100 instances of PATTERN with NEW PATTERN no matter how many may be on a line.
If you want to replace PATTERN only between certain lines that’s a little trickier:-)
Though of course do-able in vim, not I think in vi.
How do I remove the last “.” in a list of domainames
example http://www.yahoo.com. <–notice "." at the end
example http://www.google.com. <–notice "." at the end
:g/.$/s///
Chris’s answer is almost correct 🙂
:g/.$/s/// will remove the last character on the line, correct. No matter what that character is, probably not quite what you want.
Try: g/\.$/s/.$// instead or even, simpler :%s/\.$//
————————-david
Hi Folks,
Please help with below requirement. Nothing is working.
CONN kpr_cata/kpr_cata123;
@packages/kpr_item_property.sql;
CONN kpr_staging_cata/kpr_staging_cata123;
@packages/kpr_item_property.sql;
The above should look like below,
CONN kpr_cata/kpr99;
@packages/kpr_item_property.sql;
CONN kpr_staging_cata/kpr99;
@packages/kpr_item_property.sql;
Hi Praneeth,
Try this:
:%s/\/kpr_.*123;$/\/kpr99;/
Arun V
Thanks Sathiya, you saved lot of my time.
how to replace / with # in vi editor..
i want to replace “murali” with “murali/muraux” in vi editor….plsssss..help….
:%s+/+#+
:%s+murali+murali/muraux+
Arun, in the comments 55 you say that “Unfortunately there is no method to replace a particular position using vi”
But you can do this:
:%s!\v^.{32}!&,!
Is this right?
Awesome article and discussion, thanks a lot.
Rich, if you check the vim-doc/pattern.html about 2/3 down, you’ll see:
\%23c which is about working with a specific column
and just below that:
\%23v which is about working with a virtual column – a column without text
enjoy —————-david
How can you do do a text search with line delete? ‘:g/foo/ d’ does not work
Hi John,
:g/foo/d should remove any lines with ‘foo’ in them. Can not think of any reason why that wouldn’t work. Try starting Vim without ~/.vimrc to see if that makes a difference.
vim -u
————–david
I want to find and replace a word in script file in Vi editor.
Find: bmcs
Replace: /home/bmcs
Please suggest.
I want to search the word and replace the word in a script file using Vi editor.
Search: bmcs
Replace: /home/bmcs
Please suggest earliest.
Hey,
I haven’t read all the comments, maybe somebody had the same issue as I have; :%s!\~!\= expand($HOME)!g outputs ‘expand($HOME)’ and not ‘/home/helene’
Great article, thanks a lot!
how to change
http://yahoo.com to http://hotmail.com
Very useful and easy to understand tutorial. Thanks
Hi ,
Need some help,
How to add a string at the beginning of ‘n’ lines in vi editor.
Eg.
I need to add the string “#TAS000X123 REM2017MAR# at the beginning of below lines in a single go.( all lines are from same file).
02958;abcdefg;TZT_1143_B12_MUP4_CB_3btt_18;;VF-ES;;SYS;;;1440;;Su;full;32;abcdefg:31
02959;defghij;TZT_1143_B12_MUP4_CB_3btt_18;;VF-ES;;SYS;;;1440;;Mo-Sa;incr;32;abcdefg:31
02960;lmnopwd;TZT_1143_B12_MUP4_CB_3btt_18;;VF-ES;;SYS;;;1440;;We;full;32;abcdefg:31
02961;jlkfnbk;TZT_1143_B12_MUP4_CB_3btt_18;;VF-ES;;SYS;;;1440;;Th-Tu;incr;32;abcdefg:31
02974;oprlkjh;TZT_1143_B12_MUP4_CB_3btt_18;;VF-ES;;SYS;;;1440;;Th;full;32;abcdefg:31
02975;ldkjlak;TZT_1143_B12_MUP4_CB_3btt_18;;VF-ES;;SYS;;;1440;;Fr-We;incr;32;abcdefg:31
02978;dfals12;TZT_1143_B12_MUP4_CB_3btt_18;;VF-ES;;SYS;;;1440;;We;full;32;abcdefg:31
02979;adflkkk;TZT_1143_B12_MUP4_CB_3btt_18;;VF-ES;;SYS;;;1440;;Th-Tu;incr;32;abcdefg:31
As a result the each line should be updated like:-
#TAS000011051895 REM201703MAR#02979;adflkkk;TZT_1143_B12_MUP4_CB_3btt_18;;VF-ES;;SYS;;;1440;;Th-Tu;incr;32;abcdefg:31
:%s!^!#TAS000011051895REM201703MAR#!
:%s!^!#TAS000X123 REM2017MAR#!