Stepan Loginov
Stepan Loginov

Reputation: 1767

How to regex in Vim

I want to add some text before each return For example we have :

void* foo (){
   if (something){ 
   return A;
   }
do_something;
// That return word may be ignored, because it's comment
do_something;
returns(); //It may ignored to
return ;
}

I need :

void* foo (){
   if (something){
   END;
   return A;
   }
do_something;
// That return word may be ignored, becouse it's comment
do_something;
returns(); //It may ignored to
END;
return ;
}

I can't build regex for search request. It may looks like "

return"< some text here started with space symbol, or nothing >;<endline>

How I can make it in VIM?

Upvotes: 3

Views: 11000

Answers (5)

Tassos
Tassos

Reputation: 3288

You may use the global command as follows:

:g/^\s*return\>/normal OEND;

It searches for lines having any number of whitespace and the word return, executes the command O and adds the "END;"

Bonus feature the END; is 'auto indented'.

Upvotes: 2

Peter Rincker
Peter Rincker

Reputation: 45087

:%s/^\(\s*\)\<return\>/\1END;\r&/

Use & to return what was matched. Similar to \0 in Perl.

Upvotes: 0

cforbish
cforbish

Reputation: 8819

Using hold registers is an easy way to do this:

%s/^\(\s*\)\(return\>.*\)/\1END;\r\1\2/g

The meanings:

%s - global substitute
/  - field separator
^  - start of line
\( - start hold pattern
\s - match whitespace
*  - 0 or more times
\) - end hold pattern
\> - end of word boundary (prevent returns matching return)
.  - match any character
\1 - recall hold pattern number 1
\2 - recall hold pattern number 2
\r - <CR>
g  - Replace all occurrences in the line

Upvotes: 7

Manny D
Manny D

Reputation: 20714

:%s/.*\(\/\/.*\)\@<!\<return\>.*/END\r&/g

This basically says "find any line with a return statement that's not in a comment and replace it with END, newline, then the original line". The key to this is the lookbehind (\(\/\/.*\)\@<!) which essentially ignores any instances of return in a comment. The \<return\> makes sure you only search for return and not something like returns.

I tested using:

//return here
return; // return as mentioned
if (cornerCase) { return 1; }
returns();
return 0;

Which became this after the replace:

//return here
END
return; // return as mentioned
END
if (cornerCase) { return 1; }
returns();
END
return 0;

Upvotes: 0

evnu
evnu

Reputation: 6680

Use a substitution:

:%s/\(return\)/END;\r\1/g

The substitution searches for occurrences of return, remembers such occurrences and places END; followed by a newline in front of those occurrences. You may want to read up on regular expressions in vim's substitution. Note that \(\) groups characters such that a group can be referenced in the substitution again.

Edit

Lets make that example more specific (I hope I hit your corner cases):

:%s/\(return\(\((\|\s\)[^;]\)*;\)/END\r\1/g

The regular expression matches every occurrence of return which is followed by whitespace or opening parenthesis and subsequent characters until ; is encountered. Such an occurrence is substituted with itself and a prepended END.

Upvotes: 0

Related Questions