How can I do this search&replace with vim? - regex

I have a text file containing these lines:
options[15]=new Option("text1","25");
options[16]=new Option("text2","23");
options[17]=new Option("text3","12");
(and more...)
How can I replace each line with text# ?.for example first line should be replaced by text1, second line with text2,etc...

As an alternative to :s and using a macro, I sometimes find :normal to be very pleasant.
%norm df"f"d$
We can short this up but using ; motion which will repeat the f" motion and use D which is the same as d$
%norm df";D

Read :h /\(
%s/\Voptions[\d\+]=new Option("\(text\d\+\)","\d\+");/\1/g

It looks like you already have them in the source. Assuming that you have the lines like this:
options[15]=new Option("text#","25");
...
And you want to change to this:
options[15]=new Option("text15","25");
...
Here is what you do:
change the first line to text1
yank "text1"
create a macro (qq)
/text
dw
p
ctrl+a
b
vwly
q
Then if you have 25 lines: do 23#q
23 invocations of the macro since you have done the first two manually.

Related

Format a text file by regex match and replace

I have a text file that looks like the following:
Chanelle
Jettie
Winnie
Jen
Shella
Krysta
Tish
Monika
Lynwood
Danae
2649
2466
2890
2224
2829
2427
2816
2648
2833
2453
I need to make it look like this
Chanelle 2649
Jettie 2466
... ...
I tried a lot on sublime editor but couldn't figure out the regex to do that. Can somebody demonstrate if it can be done.
I tested the following in Notepad++ but it should work universally.
Use this as the search string:
(?:(\s+[A-Za-z]+)(\r?\n))((?:\s*[A-Za-z]*\r?\n)+)\s+(\d+)
and this as the replacement:
$1 $4$2$3
Running a replace with it once will do one line at a time, if you run it multiple times it'll continue to replace lines until there are no matching lines left.
Alternatively, you can use this as the replacement if you want to have the values aligned by tabs, but it's not going to match in all cases:
$1\t\t$4$2$3
While the regex answer by SeinopSys will work, you don't need a regex to do this - instead, you can take advantage of Sublime's multiple cursors.
Place your cursor at the beginning of line 1, then hold down Shift↓ to select all the names.
Hit CtrlShiftL (Selection -> Split into Lines) to split the selection into lines.
CtrlC to copy.
Place your cursor on line 11 (the first number line) and press CtrlShift↓ (Windows/OS X) or AltShift↓ (Linux) to place a cursor at the beginning of each number line.
Hit CtrlV to paste the names before the numbers.
You can now delete the names at the top and you're all set. Alternatively, you could use CtrlX to cut the names in step 3.

Have Tabulize ignore some lines and align the others

I would want Tabulize to ignore lines which do not have a particular character and then align/tabularize the lines ..
text1_temp = text_temp;
temporary_line;
text2 = text_temp;
In the end i would like the following :
text1_temp = text_temp;
temporary_line;
text2 = text_temp;
// The 2nd "=" is spaced/tabbed with relation to the first "="
If i run ":Tabularize /=" for the 3 lines together I get :
text1_temp = text_temp;
temporary_line;
text2 = text_temp;
Where the two lines with "=" are aligned with respect to the length of the middle line
Any suggestions .. ?
PS: I edited the post possibly to explain the need better ..
I am not sure how to do this with Tabular directly. You might be able to use Christian Brabandt's NrrwRgn plugin to filter out only lines with = using :NRP then running :NRM. This will give you a new buffer with only the lines with = so you can run :tabularize/=/ and then save the the buffer (:w, :x, etc).
:g/=/NRP
:NRM
:tabularize/=/
:x
The easiest option is probably to use vim-easy-align which supports such behavior out of the box it seems. Example of using EasyAlign (Using ga as EasyAlign's mapping you):
gaip=
What about a simple replace, like :g/=/s/\t/ /g ?
If that doesn't work, you can try this too: :g/=/s/ \+= \+/ = /g
Explanation:
The :/g/=/s will find all the lines that contain '=', and do the replacement for them.
So, s/\t/ /g will replace tabs with spaces. These two things combined will do what you need.

Display all lines matching a pattern in vim

I search for a particular string in a file in vim, and I want all the lines with matching string to be displayed, perhaps in another vim window.
Currently I do this:
Search for 'string'
/string
and move to next matching string
n or N
Bur, I want all the lines with matching string at one place.
For example:
1 Here is a string
2 Nothing here
3 Here is the same string
I want lines 1 and 3 to be displayed as below, highlighting string
1 Here is a string
3 Here is the same string
:g/pattern/#<CR>
lists all the lines matching pattern. You can then do :23<CR> to jump to line 23.
:ilist pattern<CR>
is an alternative that filters out comments and works across includes.
The command below:
:vimgrep pattern %|cwindow<CR>
will use Vim's built-in grep-like functionality to search for pattern in the current file (%) and display the results in the quickfix window.
:grep pattern %|cwindow<CR>
does the same but uses an external program. Note that :grep and :vimgrep work with files, not buffers.
Reference:
:help :g
:help include-search
:help :vimgrep
:help :grep
:help :cwindow
FWIW, my plugin vim-qlist combines the features of :ilist and the quickfix window.
From the comments I believe your file looks like this, i.e. the line numbers are not part of the text:
Here is a string
Nothing here
Here is the same string
You could copy all lines matching a pattern into a named register ("a" in the example below), then paste it into a new file:
:g/string/y A
:e newfile
:"ap
Which gets you:
Here is a string
Here is the same string
Alternatively, you can use the grep command and add -n to include line numbers:
:grep -n string %
1:~/tmp.txt [text] line: 3 of 3, col: 23 (All)
:!grep -nH -n string /home/christofer/tmp.txt 2>&1| tee /tmp/vHg7GcV/3
[No write since last change]
/home/christofer/tmp.txt:1:Here is a string
/home/christofer/tmp.txt:3:Here is the same string
(1 of 2): Here is a string
Press ENTER or type command to continue
By default you'll get the output in the "command buffer" down at the bottom (don't know its proper name), but you can store it in several different places, using :copen for example.
Following this answer over on the Vi StackExchange:
:v/mystring/d
This will remove all lines not containing mystring and will highlight mystring in the remaining lines.

Math in Vim search-and-replace

I have a file with times (minutes and seconds), which looks approximately as follows:
02:53 rest of line 1...
03:10 rest of line 2...
05:34 rest of line 3...
05:35 rest of line 4...
10:02 rest of line 5...
...
I would like to replace the time by its equivalent in seconds. Ideally, I would like to run some magical command like this:
:%s/^\(\d\d\):\(\d\d\) \(.*\)/(=\1*60 + \2) \3/g
...where the (=\1*60 + \2) is the magical part. I know I can insert results of evaluation with the special register =, but is there a way to do this in the subst part of a regex?
Something like this?
:%s/^\(\d\d\):\(\d\d\)/\=submatch(1)*60+submatch(2)/
When the replacement starts with a \= the replacment is interpreted as an expression.
:h sub-replace-expression is copied below
Substitute with an expression *sub-replace-expression*
*sub-replace-\=*
When the substitute string starts with "\=" the remainder is interpreted as an
expression. This does not work recursively: a substitute() function inside
the expression cannot use "\=" for the substitute string.
The special meaning for characters as mentioned at |sub-replace-special| does
not apply except for "<CR>", "\<CR>" and "\\". Thus in the result of the
expression you need to use two backslashes to get one, put a backslash before a
<CR> you want to insert, and use a <CR> without a backslash where you want to
break the line.
For convenience a <NL> character is also used as a line break. Prepend a
backslash to get a real <NL> character (which will be a NUL in the file).
When the result is a |List| then the items are joined with separating line
breaks. Thus each item becomes a line, except that they can contain line
breaks themselves.
The whole matched text can be accessed with "submatch(0)". The text matched
with the first pair of () with "submatch(1)". Likewise for further
sub-matches in ().
Use submatch() to refer to a grouped part in the substitution place:
:%s/\v^(\d{2}):(\d{2})>/\=submatch(1) * 60 + submatch(2)/
With your example yields:
173 rest of line 1...
190 rest of line 2...
334 rest of line 3...
335 rest of line 4...
602 rest of line 5...
Hopefully it would be helpful to someone else, but i had similar problem where i wanted to replace "id" with a different number, in-fact any other number
{"id":1,"first_name":"Ruperto","last_name":"Bonifayipio","gender":"Male","ssn":"318-69-4987"},
used expression
%s/\v(\d+),/\=submatch(1)*1111/g
which results into following new value
{"id":1111,"first_name":"Ruperto","last_name":"Bonifayipio","gender":"Male","ssn":"318-69-4987"},

Remove the first character of each line and append using Vim

I have a data file as follows.
1,14.23,1.71,2.43,15.6,127,2.8,3.06,.28,2.29,5.64,1.04,3.92,1065
1,13.2,1.78,2.14,11.2,100,2.65,2.76,.26,1.28,4.38,1.05,3.4,1050
1,13.16,2.36,2.67,18.6,101,2.8,3.24,.3,2.81,5.68,1.03,3.17,1185
1,14.37,1.95,2.5,16.8,113,3.85,3.49,.24,2.18,7.8,.86,3.45,1480
1,13.24,2.59,2.87,21,118,2.8,2.69,.39,1.82,4.32,1.04,2.93,735
Using vim, I want to reomve the 1's from each of the lines and append them to the end. The resultant file would look like this:
14.23,1.71,2.43,15.6,127,2.8,3.06,.28,2.29,5.64,1.04,3.92,1065,1
13.2,1.78,2.14,11.2,100,2.65,2.76,.26,1.28,4.38,1.05,3.4,1050,1
13.16,2.36,2.67,18.6,101,2.8,3.24,.3,2.81,5.68,1.03,3.17,1185,1
14.37,1.95,2.5,16.8,113,3.85,3.49,.24,2.18,7.8,.86,3.45,1480,1
13.24,2.59,2.87,21,118,2.8,2.69,.39,1.82,4.32,1.04,2.93,735,1
I was looking for an elegant way to do this.
Actually I tried it like
:%s/$/,/g
And then
:%s/$/^./g
But I could not make it to work.
EDIT : Well, actually I made one mistake in my question. In the data-file, the first character is not always 1, they are mixture of 1, 2 and 3. So, from all the answers from this questions, I came up with the solution --
:%s/^\([1-3]\),\(.*\)/\2,\1/g
and it is working now.
A regular expression that doesn't care which number, its digits, or separator you've used. That is, this would work for lines that have both 1 as their first number, or 114:
:%s/\([0-9]*\)\(.\)\(.*\)/\3\2\1/
Explanation:
:%s// - Substitute every line (%)
\(<something>\) - Extract and store to \n
[0-9]* - A number 0 or more times
. - Every char, in this case,
.* - Every char 0 or more times
\3\2\1 - Replace what is captured with \(\)
So: Cut up 1 , <the rest> to \1, \2 and \3 respectively, and reorder them.
This
:%s/^1,//
:%s/$/,1/
could be somewhat simpler to understand.
:%s/^1,\(.*\)/\1,1/
This will do the replacement on each line in the file. The \1 replaces everything captured by the (.*)
:%s/1,\(.*$\)/\1,1/gc
.........................
You could also solve this one using a macro. First, think about how to delete the 1, from the start of a line and append it to the end:
0 go the the start of the line
df, delete everything to and including the first ,
A,<ESC> append a comma to the end of the line
p paste the thing you deleted with df,
x delete the trailing comma
So, to sum it up, the following will convert a single line:
0df,A,<ESC>px
Now if you'd like to apply this set of modifications to all the lines, you will first need to record them:
qj start recording into the 'j' register
0df,A,<ESC>px convert a single line
j go to the next line
q stop recording
Finally, you can execute the macro anytime you want using #j, or convert your entire file with 99#j (using a higher number than 99 if you have more than 99 lines).
Here's the complete version:
qj0df,A,<ESC>pxjq99#j
This one might be easier to understand than the other solutions if you're not used to regular expressions!