using regex to replace unknown text - regex

Say I have the following code
int func1(int a);
int func2(int a);
int func3(int a);
Using vim search and replace, I want to turn it into this
/* This function handles action 1*/
int func1(int a);
/* This function handles action 2 */
int func2(int a);
/* This function handles action 3 */
int func2(int a);
To search for each function is simple enough, I can simply do this
/int func.
But, I don't know how I can use the value of the . in the replace section. How can this be accomplished?

You would use what is colloquially called "capture groups" (though Vim doesn't really have a name for that mechanism).
In Vim, you define a capture group by wrapping what you want to capture with escaped parentheses:
:%s/foo\(what you want to capture\)bar/what you want to capturebaz
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
and you use it with an escaped number in the range 1-9 corresponding to the position of the capture group in the pattern:
:%s/foo\(what you want to capture\)bar/\1baz
^^
See :h \(.
In this specific case:
:%s/int func\(.\)/\/* This function handles action \1 *\/\r\0
where we even use \0 which references the whole pattern.

Related

How to force rematch?

I would like to force rematch in the following scenario - I'm trying to inverse match a qualifier after each element in a list. In other words I have:
"int a, b, c" =~ m{
(?(DEFINE)
(?<qualifs>\s*(?<qualif>\bint\b|\bfloat\b)\s*+(?{print $+{qualif} . "\n"}))
(?<decl>\s*(?!(?&qualif))(?<ident>[_a-zA-Z][_a-zA-Z0-9]*+)\s*(?{print $+{ident} . "\n"}))
(?<qualifsfacet>\s*\bint\b\s*+)
(?<declfacet>[_a-zA-Z][_a-zA-Z0-9]*+)
)
^((?&qualifsfacet)*+(?!(?&decl))
|(?&qualifs)*+(?&declfacet)
|((?&qualifsfacet)
(?&declfacet)(?<negdecl>\g{lastnegdecl}(,(?&decl)))
|(?&qualifs)*+(?&declfacet)(?<lastnegdecl>\g{negdecl})
(?# Here how to force it to retry last with new lastnegdecl)))$
}xxs;
And would like to have:
a
int
b
int
c
int
As output. Currently it's only this:
a
int
int
I think this might work if there is a way to tell the regex machine to retrigger a match for the new lastnegdecl that is being captured.
Well after some trying I finally figured it out (besides the obvious whitespace issues I had in my original post):
"int a, b, c" =~ m{
(?(DEFINE)
(?<qualifs>\s*+(?<qualif>\bint\b|\bfloat\b)\s*+(?{print $+{qualif} . "\n"}))
(?<decl>\s*+(?!(?&qualif))(?<ident>[_a-zA-Z][_a-zA-Z0-9]*+)\s*(?{print $+{ident} . "\n"}))
(?<qualifsfacet>\s*+(\bint\b|\bfloat\b)\s*+)
(?<declfacet>\s*+[_a-zA-Z][_a-zA-Z0-9]*+\s*+)
)
^((?&qualifsfacet)(?!(?&decl))
|(?&qualifs)*+(?&declfacet)
|(?<restoutter>(?=(?&qualifsfacet)(?&declfacet)
(?<rest>(?(<rest>)\g{rest}),(?&decl)))
((?&qualifs)(?&declfacet)\g{rest}|(?&restoutter)))
|(?&qualifsfacet)(?&declfacet)(,(?&declfacet))*+)$
}xxs;
Basically I'm doing a positive lookahead where decl are called with code but qualifs are not while also concatenating decl inside rest then doing a partial match with the qualifs and the rest and if it doesn't match it goes to do the same thing again. Maybe someone can explain it better but it works. The output of the program above is:
a
int
b
int
c
int
And there is a full match.

How can I used regular expressions to find all lines of source code defining a default arguments for a function?

I want to find lines of code which declare functions with default arguments, such as:
int sum(int a, int b=10, int c=20);
I was thinking I would look for:
The first part of the matched pattern is exactly one left-parenthesis "("
The second part of string is one or more of any character excluding "="
exactly one equals-sign "="
a non-equal-sign
one or more characters except right parenthesis ")"
")"
The following is my attempt:
([^=]+=[^=][^)]+)
I would like to avoid matching condition-clauses for if-statements and while-loops.
For example,
int x = 5;
if (x = 10) {
x = 7;
}
Our regex should find functions with default arguments in any one of python, Java, or C++. Let us not assume that function declarations end with semi-colon, or begin with a data-type
Try this:
\([^)]*\w+\s+\w+\s*=[^),][^)]*\)
See live demo.
It looks for words chars (the param type), space(s), word chars (the param name), optional space(s), then an equals sign.
Add ".*" to each end to match the whole line.
Please check this one:
\(((?:\w+\s+[\w][\w\s=]*,*\s*){1,})\)
The above expression matches the parameter list and returns it as $1 (Group 1), in case it is needed for further processing.
demo here

C++ Formatter to Un-split lines

Is there a program (like Astyle) which can UN-split lines?
Example:
// These
void foo(
int one,
int two,
double three);
double a = b *
c;
// Becomes this
void foo(int one, int two, double three);
double a = b * c;
Using any decent IDE with regex search replace capabilities you can match this: ,\s*\r\n\s*(.*)
And replace with this: , $1
This assumes \r\n is your newline match and $1 is how you print your first capture.
EDIT:
This is an easy change to your match code if you want to add in some other symbols: [,+*-]\s*\r\n\s*(.*)
One thing you'll have to look out for is commented lines like this:
// blah,
// blah*
// blah
Because the regex will pick them up as well.

How to Modify all beginnings and endings of a function

I would like to modify all the function which are of the following kind:
returnType functionName(parameters){
OLD_LOG; // Always the first line of the function
//stuff to do
return result; // may not be here in case of function returning void
} // The ending } is not always at the beginning of the line (but is always the first not white space of the line and has the same number of white space before than 'returnType' does)
by
returnType functionName(parameters){
NEW_LOG("functionName"); // the above function name
//stuff to do
END_LOG();
return result; //if any return (if possible, END_LOG() should appear just before any return, or at the end of the function if there is no return)
}
There is a at least a hundred of those functions.
Therefore I would like to know if it is possible to do that using a "look for/replace" in a text editor supporting regex for exemple, or anything else.
Thank you
here is an attempt for the same
Regex
/(?<=\s)(\w+)(?=\()(.*\{\n.*)(OLD_LOG;)(.*)(\n\})/s
Test String
returnType functionName(parameters){
OLD_LOG;
//stuff to do
}
Replace string
\1 \2NEW_LOG("\1");\n\4\n END_LOG();\5
Result
returnType functionName (parameters){
NEW_LOG("functionName");
//stuff to do
END_LOG();
}
live demo here
I have updated the regex to include optional return statement & optional spaces
Regex
/(?<=\s)(\w+)(?=\()(.*\{\n.*)(OLD_LOG;)(.*?)(?=(?:\s*)return|(?:\n\s*\}))/s
Replace string
\1 \2NEW_LOG("\1");\n\4\n END_LOG();
demo for return statement
demo for optional spaces
see if this works for you
Find
(\n([^\S\n]*)[^\s].*\s([^\s\(]+)\s*\(.*\)\s*\{\s*\n)(\s*)OLD\_LOG;((.*\s*\n)*?)(\s*return\s.*\r\n)?\2\}
Replace with
\1\4NEW\_LOG\(\"\3\"\);\5\4END_LOG\(\);\r\n\7\2\}
Notice that \n and \r\n are used. If your code file uses a different newline format, you need to modify accordingly.
Limitations of this replace are these assumptions:
1) OLD_LOG; is just one line below the function name.
2) Function has return type (any non space character before the function name is okay).
3) Function name and { are at the same line.
4) Ending } has the same number of white space before than 'returnType' does, and there is no such } inside the function.
5) Last return is just one line above the ending }.
It may be faster to use an editor with multiple carets support (e.g. Sublime Text, IntelliJ):
https://stackoverflow.com/a/18929134/802365
(Video) Multi-caret editing in Sublime Text

vim regex to match inline comments

Assuming the following sample inline comment:
/*
function newMethodName (int bar, String s) {
int i = 123;
}
s/\<foo\s*(/newMethodName (/g
*/
How would I match and replace such that it would, essentially, become uncommented. I got this far before giving up.
:%s/\/\*\(\_.\)*\*\//\1/
Solution
:%s/\/\*\(\_.*\)\*\//\1/
Your capture group ( ) is capturing one character or newline. Put the following * inside so that \1 replacement gets the whole string rather than just the first character.