Let's say I have the following text
bar1 = foo.get('abc1')
bar2 = foo.get('abc2')
bar3 = foo.get('abc3')
and I would like to search and replace all the occurrences of foo.get(...) with foo[...] in order to obtain:
bar1 = foo['abc1']
bar2 = foo['abc2']
bar3 = foo['abc3']
How could I do that in vim in one search/replace command?
The following should work: :%s/foo.get(\(\W\+\)\(\w\+\)\(\W\+\))/foo\[\1\2\3].
Here, the main logic is to store ', abc1 and ' to \1, \2 and \3 which can later be back referenced. Similarly for other two lines.
The simplest way I think would be to select those three lines using VISUAL mode (press v, and hjkl/arrows to select the lines) - the advantage of visual mode is that you can select which lines to launch the substitute command on.
then press : to launch a command on those lines selected in visual mode (:'<,'>part should add itself automatically):
:'<,'>s/foo.get('\(.*\)')/foo['\1']
so this simple regex basically selects foo.get('somewords') and replaces them with foo['somewords'] (somewords being group 1)
Another solution would be:
:g/foo\.get/exec "norm! f(r[\<Esc>f)r]"
Let's break down the whole command to be more didactic:
g/foo\.get/ .................... match all the lines with "foo.get"
exec ........................... calls command execution
norm! .......................... normal mode
f(r[ ........................... jumps to the ( and replaces it with [
\<Esc> ......................... literal Esc (only works between double quotes)
f)r] ........................... the final substitution
If you just want a one shot regex for this specific pattern, you can use:
:%s/foo\.get(\(.*'\))/foo[\1]/c
or if there are possible spaces to contend with:
:%s/foo\.get *(\(.*'\) *)/foo[\1]/c
The /c is for a prompt to confirm the replacement, and can be left off if desired.
Related
I am using VS Code (with vim plugin), how would I insert text after the first word of each sentence on multiple lines? I would like to know how to do this strictly with multi-cursor, not macros, search/replace, etc.
I would like to turn this:
Hi how are you?
Ahoy how are you?
Howdy how are you?
into this:
Hi, how are you?
Ahoy, how are you?
Howdy, how are you?
Use a single command
:%norm ea,
: ................... command mode
% ................... whole file
norm ............... normal mode
e .................. end of a word
a .................. append charactere
The easiest is to select your lines with Selection/Column Selection Mode enabled. Select the first column (there are other ways to get a cursor at the beginning of each of your selected lines - such as
(1) Select all your lines
(2) Shift+Alt+I to put a cursor at the end of each line
(3) Home to move all those to the beginning
Then you'll need to bind this command
cursorWordPartRight
to some keybinding. Trigger that keybinding and type your ,.
I have text like this:
w ky,
wyz,
wyy,
wj,
w w,
and I want to change it to this:
"w ky",
"wyz",
"wyy",
"wj",
"w w",
I do it now using:
record a macro to insert double quota in one line, then go to next line qa0wi"$i"j
then just type 4#a
Yes, it works, but is there an easier way to do this?
There is an easier way. You can use the norm command. I would recommend this:
Visually select all of the lines
Type
:norm I"<C-v><esc>$i"<cr>
When you actually type this (before hitting enter), the text that should be shown in your command line is:
:'<,'>norm I"^[$i"
The norm command tells vim to simulate a set of normal mode keystrokes on certain lines. In this case, the command is:
:'<,'> " On every line in the visual selection:
norm " Do the following as if typed in normal mode:
I"<esc>$i" " Insert an '"', escape, then insert a '"' at the end (before the comma)
You can also do this without using a visual selection, by typing <n>:norm ..., and the command will apply the current n lines. (the current line and the next n-1 lines)
Doing a "very magic search \v" we can search...
\v(\w ?\w+),
\v ........... starts very magic search mode
( ........... starts group one
\w ........... any word
? ........... optional space
+ ........... one or more
) ........... ends group one
After testing the search we can pass into our command or
use the last search by placing two slashes on the search pattern
%s/\v(\w ?\w+),/"\1",/g
%s//"\1",/g
everything matched on group one can be referred by \1.
Do a basic multi-line edit at the front then do a string replace on , with ",.
In Vim, I have the following text:
key => value1
key => value2
key => value1111
key => value12
key => value1122222
I would like to add "," at the end of each line. The previous text will become the following:
key => value1,
key => value2,
key => value1111,
key => value12,
key => value1122222,
Does anyone know how to do this? Is it possible to use visual block mode to accomplish this?
This will do it to every line in the file:
:%s/$/,/
If you want to do a subset of lines instead of the whole file, you can specify them in place of the %.
One way is to do a visual select and then type the :. It will fill in :'<,'> for you, then you type the rest of it (Notice you only need to add s/$/,/)
:'<,'>s/$/,/
There is in fact a way to do this using Visual block mode. Simply pressing $A in Visual block mode appends to the end of all lines in the selection. The appended text will appear on all lines as soon as you press Esc.
So this is a possible solution:
vip<C-V>$A,<Esc>
That is, in Normal mode, Visual select a paragraph vip, switch to Visual block mode CTRLV, append to all lines $A a comma ,, then press Esc to confirm.
The documentation is at :h v_b_A. There is even an illustration of how it works in the examples section: :h v_b_A_example.
Another solution, using another great feature:
:'<,'>norm A,
See :help :normal.
ex mode is easiest:
:%s/$/,
: - enter command mode
% - for every line
s/ - substitute
$ - the end of the line
/ - and change it to
, - a comma
The substitute command can be applied to a visual selection. Make a visual block over the lines that you want to change, and type :, and notice that the command-line is initialized like this: :'<,'>. This means that the substitute command will operate on the visual selection, like so:
:'<,'>s/$/,/
And this is a substitution that should work for your example, assuming that you really want the comma at the end of each line as you've mentioned. If there are trailing spaces, then you may need to adjust the command accordingly:
:'<,'>s/\s*$/,/
This will replace any amount of whitespace preceding the end of the line with a comma, effectively removing trailing whitespace.
The same commands can operate on a range of lines, e.g. for the next 5 lines: :,+5s/$/,/, or for the entire buffer: :%s/$/,/.
:%s/$/,/g
$ matches end of line
If you want to add ',' at end of the lines starting with 'key', use:
:%s/key.*$/&,
I have <M-DOWN>(alt down arrow) mapped to <DOWN>. so that I can repeat the last command on a series of lines very quickly. with this mapping I can:
A,<ESC>
And then hold alt while pressing down repeatedly to append the comma to the end of each line.
This works well for me because it allows very good control over what lines do and do not get the change.
(I also have the other arrows mapped similarly to allow for easy repeating of .)
Here's the mapping line to paste into your vimrc:
map <M-DOWN> <DOWN>.
Following Macro can also be used to accomplish your task.
qqA,^[0jq4#q
In Vim, if I have code such as (in Ruby):
anArray << [anElement]
and my cursor is on the first [, I can hop to ] with the % key, and I can delete all the content between the [] pair with d%, but what if I just want to delete the [ and ] leaving all the remaining content between the two. In other words, what's the quickest way to get to:
anArray << anElement
One can take advantage of the text objects that are built in into Vim
(see :help text-objects). The desired edit can be stated as a
sequence of the following three actions.
Cut the text inside the square brackets:
di[
Select the (empty) square brackets:
va[
Alternatively, you can just select the character under the
cursor and the one to the left of it, because the command
from step 1 always puts the cursor on the closing bracket:
vh
Paste the cut text over the selected brackets:
p
Altogether, it gives us the following sequence of Normal-mode commands:
di[va[p
or, when the alternative form of step 2 is used:
di[vhp
ma%x`ax (mark position in register a, go to matching paren, delete char, go to mark a, delete char).
EDIT:
%x``x does the same thing (thanks to #Alok for the tip).
Using the Surround plugin for Vim, you can eliminate surrounding delimiters with ds<delimeter>.
To install it via Vundle plugin, add
Plugin 'tpope/vim-surround'
to your .vimrc file and run :PluginInstall.
If you have issues with the marks pointing to the first char of the line or with using % ...
di[vhp
works as well... It deletes matching [] brackets, when the cursor is anywhere inside. '[' can be replaced by '{' or '(' .
The other answers work fine if you want to delete delimiters one line at a time.
If on the other hand you want to remove a function and it's delimiters from the entire file use:
:%s/function(\(.*\))/\1/g
which replaces function(arguments) with arguments everywhere in the file.
You can use d% while your cursor is on the bracket/parentheses.
Say I have ten lines and I want to prepend text to some word that occurs in those lines? It does not have to be at the beginning of the line.
From:
sdfsd foo sdfsd
sfsd foo fsdf
sdfsdf foo sdfsdf
to:
sdfsd bar(foo sdfsd
sfsd bar(foo fsdf
sdfsdf bar(foo sdfsdf
Is it also possible to not only prepend the bar( but actually surround foo with bar(foo)?
I would also like a quick way to append // comments to multiple lines (C-style comments).
I use Vim/GVim 7.2.
Go to the first foo, press Ctrl-v to enter visual block mode and press down until all the lines with foo are marked. Then press Shift-i to insert at the beginning (of the block). When you are finished and press Esc, the inserted characters will be added to each line at the left of the marked block.
To insert at the end, press again Ctrl-v, move up/down to mark all affected lines and then press End or $ to extend the selection until the end of the lines. Now you can press Shift-a to append at the end of all the lines, just like previously with Shift-i.
The visual selection can also be done with normal movement commands. So to comment a whole block in C you could move to the opening brace and type Ctrl-v % Shift-i // Esc.
To answer your first question, the below
:%s/foo/bar(&)/g
will look for foo, and surround the matched pattern with bar(). The /g will do this multiple times in one line.
Since you're just matching foo, you could do a simple :s/foo/bar(foo)/g. The above will work, however, if you decide to match on a regular expression rather than a simple word (e.g. f[a-z][a-z]). The '&' in the above represents what you've matched.
To prefix a set of lines I use one of two different approaches:
One approach is the block select (mentioned by sth). In general, you can select a rectangular region with ctrl-V followed by cursor-movement. Once you've highlighted a rectangle, pressing shift-I will insert characters on the left side of the rectangle, or shift-A will append them on the right side of the rectangle. So you can use this technique to make a rectangle that includes the left-most column of the lines you want to prefix, hit shift-I, type the prefix, and then hit escape.
The other approach is to use a substitution (as mentioned by Brian Agnew). Brian's substitution will affect the entire file (the % in the command means "all lines"). To affect just a few lines the easiest approach is to hit shift-V (which enables visual-line mode) while on the first/last line, and then move to the last/first line. Then type:
:s/^/YOUR PREFIX/
The ^ is a regex (in this case, the beginning of the line). By typing this in visual line mode you'll see '<,'> inserted before the s automatically. This means the range of the substitution will be the visual selection.
Extra tip: if your prefix contains slashes, you can either escape them with backslash, or you can use a different punctuation character as the separator in the command. For example, to add C++ line comments, I usually write:
:s:^:// :
For adding a suffix the substitution approach is generally easier unless all of your lines are exactly the same length. Just use $ for the pattern instead of ^ and your string will be appended instead of pre-pended.
If you want to add a prefix and a suffix simultaneously, you can do something like this:
:s/.*/PREFIX & SUFFIX/
The .* matches the whole line. The & in the replacement puts the matched text (the whole line) back, but now it'll have your prefix and suffix added.
BTW: when commenting out code you'll probably want to uncomment it later. You can use visual-block (ctrl-V) to select the slashes and then hit d to delete them, or you can use a substitution (probably with a visual line selection, made with shift-V) to remove the leading slashes like this:
:s:// ::
:normal to the rescue!
:%norm Wibar(
:%norm WEa)
:norm(al) replays the commands as if you had typed them:
W - goes to the next word
i - starts insertion mode
bar( - types the sequence 'bar('
Or in one line:
:%norm Wibar(ctrlvESCEa)
If you're running Windows then type ctrlq instead of ctrlv.
Yet another possibility (probably not-so-useful in your test case, but handy in other situations) is to cordon off the area you want to change with marks.
Put the cursor anywhere in the top line and press 'a
Put the cursor anywhere in the last line and press 'b
Issue the command :'a,'b s/foo/bar(&)/
I usually like visual block mode if everything is visible on the screen, and I usually prefer marks if the start and stop are separated by many screens.
Another simple regular expression is:
%s/^/<text you want to prepend>/
For the C-style comments, use the regexp answer by Brian, and match on line ending $, and insert away.