How to get string between two commands in vim - regex

I'm trying to write a vim script for get string between two commands. eg:
\string{new strings}, I want to get the new string if it contain empty lines or space
:%s/\\string{[^}]*\n*[^}]*}/new/gec

Your requirement is not that clear, but if you want to
get the "new string" if it contain empty lines or space
Also you commented:
select the contents inside the curly brace of \string{} even if there is any space or line
This line does it, it is a search command, not :s
/\\string{\zs\_[^}]*
If you want to do some substitution on the content between \string{ and }, you can use the pattern:
%s/\\string{\zs\_[^}]*\ze}/whatever/g
Note that, you can also write s/\\string{\zs\_[^}]*/whatever/g, the \ze} will make sure that the closing bracket must be there. Not sure if this is needed.
For the detail of \_[], do a :h \_[

use this code
%s/\\string{[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]*\n*[^}]
*}/new/gec

Related

Remove line entirely (not to leave it empty)

This is what I have in doc:
1;01878916;BC101;FALSE
16;01978916;BC101;FALSE
17;0195B4E5;BC101;FALSE
19;0197D016;BC101;FALSE
After I run find&replace: ^((1|17);.+?)$ with: empty it leaves
blankrow
16;01978916;BC101;FALSE
blankrow
19;0197D016;BC101;FALSE
and then I have to run find and replace \s+$ in order to remove empty line(s) and manually remove first empty line.
Im weak with regex, tried to combine those 2 commands into one.
How it should be, to remove entirely empty rows, without leaving empty row?
To get
16;01978916;BC101;FALSE
19;0197D016;BC101;FALSE
Thanks in advance. I need to have regex commands in order to run FIND and Replace in all open files, because I'm doing this in 10 files at once. Line operations > Remove blank lines is not an option.
The regex:
^(1|17);.+?\s+
mentioned above works well here as there is no whitespace at the beginning of the lines you want to keep. If that's ever not the case, you can also do:
\s+^(1|17);.+?$

Vim regex matching multiple results on the same line

I'm working on a project where I'm converting an implementation of a binary tree to an AVL tree, so I have a few files that contain lines like:
Tree<int>* p = new Tree<int>(*t);
all over the place. The goal I have in mind is to use a vim regex to turn all instances of the string Tree into the string AVLTree, so the line above would become:
AVLTree<int>* p = new AVLTree<int>(*t);
the regex I tried was :%s/Tree/AVLTree/g, but the result was:
AVLTree<int>* p = new Tree<int>(*t);
I looks to me like when vim finds something to replace on a line it jumps to the next one, so is there a way to match multiple strings on the same line? I realize that this can be accomplished with multiple regex's, so my question is mostly academic.
Credit on this one goes to Marth for pointing this out. My issue was with vim's gdefault. By default it's set to 'off', which means you need the /g tag to make your search global, which is what I wanted. I think mine was set to 'on', which means without the tag the search is global, but with the tag the search is not. I found this chart from :help 'gdefault' helpful:
command 'gdefault' on 'gdefault' off
:s/// subst. all subst. one
:s///g subst. one subst. all
:s///gg subst. all subst. one

How to use VI to remove ocurance of character on lines matching regex?

I'm trying to change the case of method names for some functions from lowercase_with_underscores to lowerCamelCase for lines that begin with public function get_method_name(). I'm struggling to get this done in a single step.
So far I have used the following
:%s/\(get\)\([a-zA-Z]*\)_\(\w\)/\1\2\u\3/g
However, this only replaces one _ character at a time. What I would like it a search and replace that does something like the following:
Identify all lines containing the string public function [gs]et.
On these lines, perform the following search and replace :s/_\(\w\)/\u\1/g
(
EDIT:
Suppose I have lines get_method_name() and set_method_name($variable_name) and I only want to change the case of the method name and not the variable name, how might I do that? The get_method_name() is more simple of course, but I'd like a solution that works for both in a single command. I've been able to use :%g/public function [gs]et/ . . . as per the solution listed below to solve for the get_method_name() case, but unfortunately not the set_method_name($variable_name) case.
If I've understood you correctly, I don't know why the things you've tried haven't worked but you can use g to perform a normal mode command on lines matchings a pattern.
Your example would be something like:
:%g/public function [gs]et/:s/_\(\w\)/\u\1/g
Update:
To match only the method names, we can use the fact that there will only be method names before the first $, as this looks to be PHP.
To do that, we can use a negative lookbehind, #<!:
:%g/public function [gs]et/:s/\(\$.\+\)\#<!_\(\w\)/\u\2/g
This will look behind #<! for any $ followed by any number of characters and only match _\(\w\) if no $s are found.
Bonus points(?):
To do this for multiple buffers stick a bufdo in front of the %g
You want to use a substitute with an expression (:h sub-replace-expression)
Match the complete string you want to process then pass that string to a second substitute command to actually change the string
:%s/\(get\|set\)\zs_\w\+/\=substitute(submatch(0), '_\([A-Za-z]\)', '\U\1', 'g')
Running the above on
get_method_name($variable_name)
set_method_name($variable_name)
returns
getMethodName($variable_name)
setMethodName($variable_name)
To have vi do replace sad with happy, on all lines, in a file:
:1, $ s/sad/happy/g
(It is the :1, $ before the sed command that instructs vi to execute the command on every line in the file.)

Vim: How to apply external command only to lines matching pattern

Two of my favorite Vim features are the ability to apply standard operators to lines matching a regex, and the ability to filter a selection or range of lines through an external command. But can these two ideas be combined?
For example, I have a text file that I use as a lab notebook, with notes from different dates separated by a line of dashes. I can do something like delete all the dash-lines with something like :% g/^-/d. But let's say I wanted to resize all the actual text lines, without touching those dash lines.
For a single paragraph, this would be something like {!}fmt. But how can this be applied to all the non-dash paragraphs? When I try what seems the logical thing, and just chain these two together with :% v/^-/!fmt, that doesn't work. (In fact, it seems to crash Vim...)
Is there a way to connect these two ideas, and only pass lines (not) matching a pattern into an external command like fmt?
Consider how the :global command works.
:global (and :v) make two passes through the buffer,
first marking each line that matches,
then executing the given command on the marked lines.
Thus if you can come up with a command – be it an Ex command or a command-line tool – and an associated range that can be applied to each matching line (and range), you have a winner.
For example, assuming that your text is soft-wrapped and your paragraphs are simply lines that don't begin with minus, here's how to reformat the paragraphs:
:v/^-/.!fmt -72
Here we used the range . "current line" and thus filtered every matching line through fmt. More complicated ranges work, too. For instance, if your text were hard-wrapped and paragraphs were defined as "from a line beginning with minus, up until the next blank line" you could instead use this:
:g/^-/.,'}!fmt -72
Help topics:
:h multi-repeat
:h :range!
:h :range
One way to do it may be applying the command to the lines matching the pattern 'not containing only dashes'
The solution I would try the is something like (not tested):
:g/\v^(-+)#!/normal V!fmt
EDIT I was doing some experiments and I think a recurvie macro should work for you
first of all set nowrapscan:
set nowrapscan
To prevent the recursive macro executing more than you want.
Then you make a search:
/\v^(-+)#!
Test if pressing n and p works with your pattern and tune it up if needed
After that, start recording the macro
qqn:.!awk '{print $2}'^M$
In this case I use awk as an example .! means filter current line with an external program
Then to make the macro recursive just append the string '#q' to the register #q
let #q .= '#q'
And move to the beggining of the buffer to apply the recursive macro and make the modifications:
gg#q
Then you are done. Hope this helps

RegEx for VB.net

I have a txt file with content
$NETS
P3V3_AUX_LGATE; PQ6.8 PU37.2
U335_PIN1; R3328.1 U335.1
$END
need to be updated in this format, and save back to another txt file
$NETS
'P3V3_AUX_LGATE'; PQ6.8 PU37.2
'U335_PIN1'; R3328.1 U335.1
$END
NOTE: number of lines may go up to 10,000 lines
My current solution is to read the txt file line by line, detect the presence of the ";" and newline character and do the changes.
Right now i have a variable that holds ALL the lines, is there other way something like Replace via RegEx to do the changes without looping thru each line, this way i can readily print the result
and follow up question, which one is more efficient?
Try
ResultString = Regex.Replace(SubjectString, "^([^;\r\n]+);", "'$1';", RegexOptions.Multiline)
on your multiline string.
This will find any string (length one or more) at the start of a line up until the first semicolon if there is one and replace it with its quoted equivalent.
It should be more efficient than looping through the string line by line as you're doing now, but if you're in doubt, you'd have to profile it.
You could probably find all the matches using something like \w+; but I don't know how you'd be able to do a replace on that using Regex.Replace to add the 's but keep the original match.
However, if you already have it as one variable, you don't have to read the file again, either you could make your code find all ;s and then find the previous newline for each, or you could use a String.Split on newlines to split the variable you've already got into lines.
And if you want to get it back to one variable you can just use String.Join.
Personally I'd normally use the String.Split (and possibly the String.Join if needed) method, since I think that would make the code easy to read.
I would say Yes! this can be done with Regular expressions. Make sure you got the "multiline" option turned on and craft your regular expression using some capture groups to ease the work.
I can however say this will NOT be the optimal one. Since you mention the amount of lines you could be processing, it seems 'resource wise' smarter to use a streaming approach instead of the in memory approach.
Taking the Regex approach (and this took 15 mins so please don't think this is an optimal solution, just prove it would work)
private static Regex matcher = new Regex(#"^\$NETS\r\n(?<entrytitle>.[^;]*);\s*(?<entryrest>.*)\r\n(?<entrytitle2>.[^;]*);\s*(?<entryrest2>.*)\r\n\$END\r\n", RegexOptions.Compiled | RegexOptions.Multiline);
static void Main(string[] args)
{
string newString = matcher.Replace(ExampleFileContent, new MatchEvaluator(evaluator));
}
static string evaluator(Match m)
{
return String.Format("$NETS\r\n'{0}'; {1}\r\n'{2}'; {3}\r\n$END\r\n",
m.Groups["entrytitle"].Value,
m.Groups["entryrest"].Value,
m.Groups["entrytitle2"].Value,
m.Groups["entryrest2"].Value);
}
Hope this helps,