ChatGPT解决这个技术问题 Extra ChatGPT

Vim: Replacing a line with another one yanked before

vim

At least once per day i have the following situation:

A: This line should also replace line X
...
X: This is line should be replaced

I believe that I don't perform that task efficiently.

What I do:

Go to line A: AG

Yank line A: yy

Go to line X: XG

Paste line A: P

Move to old line: j

Delete old line: dd

This has the additional disadvantage that line X is now in the default register, which is annoying if I find another line that should be replaced with A. Yanking to and pasting from an additional register ("ayy, "aP) makes this simple task even less efficient.

My Questions:

Did I miss a built-in Vim command to replace a line yanked before?

If not, how can I bind my own command that leaves (or restores) the yanked line in the default register?

This is my single biggest issue with Vim's editing model. I'd love to know a solution. A CUA editor distinguishes between cut and delete, so you just cut some text, then you can go delete and paste all you want. With Vim, any delete you make trashes your cut text. You end up using far more keystrokes than you would another editor.
@sehe I'm perfectly aware of registers, but that adds 4 keystrokes per cut/paste operation and requires more forethought. When you're doing a lot of editing, that adds up quick.
Other than saving a few bytes of memory, is there an advantage to using the black hole register as opposed to any other register? I would argue that any register can be a black hole register if you do not read back from it.

D
Dorian

Vp: select line, paste what was yanked


VP works just as well, which is handy because you can keep Shift held for the whole sequence.
very nice trick, though it's worth noting a (maybe) significant caveat: this causes the yank register to be updated with the contents of the line that is being overwritten, so it might not play nicely with some tasks - e.g. if you want to overwrite the same line onto multiple destinations.
@underscore_d, it plays nicely if you do V"0p, which pastes from the last yanked register.
@timblaktu Can you explain what V"0p does? V goes into Visual line line mode and p is for pasting. What are " and 0 for? Thanks
@theprogrammer " is for register and 0 is the yank register. So "0 tells p to paste from the yank register. This register is separate from the default register, which is what Vp will obliterate (yank populates both default and its own register).
i
icecrime

What I would do :

aG Y xG Vp

You don't have to leave normal mode, but it does yank the line. You can however use V"0p which will always put the line yanked in step 2.


@duddle: yes, Y is synonym for yy
Steps 1 and 2 can be combined using :ay [E.g. :20y] Followed by Vp should do the trick. You do not have to go to a line to yank it.
If you overwrite additional lines with ccCTRL+r0ESC instead of V"0p then all following lines can be replaced with just . (the repeater)
I don't understand what is aG ? a will enter the insert mode one character after the cursor and G will just insert a capital G letter.
@vdegenne I think "a" is just standing in for the line number. So in Normal mode, 36G would be "go to line 36".
E
Eugene Yarmash

This has the additional disadvantage that line X is now in the default register, which is annoying if I find another line that should be replaced with A.

To delete text without affecting the normal registers, you can use the Black hole register "_:

"_dd

I added some mappings to my .vimrc to make d and dd always use the black hole, and x and xx perform what most editors would call a "cut" (delete and save to default register): noremap x d noremap xx dd noremap d "_d noremap dd "_dd
I am wary of remapping things in VIM, because this may not be easy on other computers, or in VIM-style plugins for IDE's. Also VIM's designers tend to have solved problems with default mappings if you really dig.
R
RichardW

Building on the answers that suggest using Vp or VP to paste over a line -- to avoid changing the contents of the yank register I find the most ergonomic command is simply:

VPY


This is the simplest solution that leaves the yank contents the same. Many thanks!
n
naught101

yy j (move to the line you want to replace),and then Vp (uppercase v and then p, will replace with the yanked content)


awesome! Very short indeed and makes it easy to select multiple lines with visual mode. It also keeps the paste buffer intact. It's annoying when dd overwrites that buffer...
@Aktau this does not leave the buffer intact.
s
sehe

I would use commandline (Ex) mode and do the following two commands

:XmA
:Ad

This simply moves line X to just under A, then deleting A moves that line up

For example

:7m3
:3d

Can you give an example? When I press e.g. 50Gm30G Vim goes to line 50 and then to the bottom and that's it. Also :Ad doesn't do anything for A=50 or A=50G
W
Wrzlprmft

Move to the start of the first line. y, $ – copy the line without the linebreak at the end Move to the start of the target line. V, p – replace just one target line c, c, Ctrlr, 0, Esc – replace the target line with the original yank Move to the start of the next target line. . – repeats the command issued at 4.2.

Notes:

4.1 is y, $ because if you do y, y or Y you will copy the linebreak, and Ctrlr, 0 actually adds the linebreak below your target line.

4.2 replaces V p, which doesn’t work with repeat because technically the last action is delete, so . would just delete a line.

If anyone knows how to issue ‘replace current line with register’ from EX mode (command line), I would like to hear from you (and to know where you found the documentation). There may be a repeatable EX command which is faster than 4.2 and/or does not have the linebreak caveat.


Step 4.2 is the killer here, as you can now repeat the entire process with dot command as in 4.3 -- that's what vim is all about!
I don't get this. 'AG' puts my maker at the end of the line, enters insert mode and enters a 'G'. What is it that I don't get?
@gustafbstrom fair criticism - sorry the A was supposed to represent the line number, but I failed to point that out. Edited.
K
Kozmonaut

You can also do:

Vy (in normal mode at the line you want to copy)
Vp (in normal mode at the line you want to replace)

Doesn't create spaces or line ends.

Cursor is placed at the start of the copied text.

The same keys can be used to yank/paste more than one line.

V (in normal mode at what you want to yank)
(use jk to move the selection)
y (to yank the selection)
V (in normal mode at where you want to paste)
(use jk to move the selection)
p (to replace the selection with the yanked lines)

B
Brian Rasmussen

Here's what I would do

Move beginning of line A, AG (where A is a line number obviously)

Yank line to some register, e.g. a (without new line). Type "ay$

Move to insert line, XG

Substitute line, S

Insert from register a, Ctrl-Ra


N
Nathan Fellman

You can use this with visual mode.

Go to line A: AG

Select the line with visual mode: VESC

go to line X: XG

Enter substitute mode for the line: S

Paste the line you copied: shift+insert (or whatever other you mapping you have for pasting from the clipboard).


Ah. Didn't know about V and S. However, your steps do not work for me as I don't yank to my OS clipboard, which is the only one I can access in insert mode. So I would have to leave insert mode first.
n
nkalvi

In light of the recent comment by cicld (thank you!), I see that I didn't grasp the original issue fully. Moving the line is not appropriate, but copying is (since the line is yanked.) So I would revise it to:

:1t20:20d_

Copy the 1st line (:t command is an alias for :copy) after line 20 (will place it on line 21) Delete line 20, putting the deleted line into the 'blackhole' register (_) (i.e. not affecting the current yank buffer)

As mentioned in the recent comment, this will not affect the current cursor position.


N
Nafaa Boutefer

You can use this commands in Normal Mode:

:AmX | Xd

the m command is for m[ove], which moves the line number A after the line number X, if you want to copy instead of move the line, use co[py]. the d command is for d[elete].

You can move(copy using co) a range of lines using

:start,end m X

B
Bharad

:ay (where a is the line number. Example :20y). This yanks a line(pun intended). Vp


n
nk3181544

I find it easier to use Ex command for this; ex. to move line 9 to 46:

 :46|9m.|-1d

This will move the cursor to line 46, move line 9 below the current, then delete the previous line (since moved line is the current one).

Or using mark(s), using mark 'a':

:46ma a|9m'a|'ad

The beauty of EX commands are that you can run them wherever your cursor is (in normal mode). I prefer :1m20|.+1d (move line 1 to line 20 and delete the next line, i.e., text that was at line 20 previously). Same idea though!
R
Ron

I often have to Y one line and replace it in multiple places, each of which have a different value (which means that I can't do a regex).

Y to yank the desired original line

and then on every line that you'd like to replace, VpzeroY


j
j5shi

i would simple use the "Black hole" register:

given:

nnoremap < C-d > "_dd

the solution would be:

< C-d >yy


G
Gregory

If you only want to change part of the line you can do that this way:

Move to position of what part of text you want to copy

y,$ - Yank from cursor to EndOfLine

move to position where you want to replace

v,$,p - replace from cursor to EndOfLine with contents of register