How can I duplicate lines matching a pattern, and

2019-03-31 23:08发布

问题:

I'm trying to add an attribute to a java class, using VIM as the editor. Therefore I thought I could use a command to ease my work with all the boilerplate code. Eg:

All lines containing "atributeA", like this one

this.attributeA=attributeA //basic constructor

should turn into

this.attributeA=attributeA //basic constructor
this.attributeB=attributeB //basic constructor

Is it possible?

回答1:

Having the solution be a one-liner as a requirement seems a little odd, since you can assign any sequence of keystrokes or any function or command to a keypress in Vim if you like.

That being said, this type of thing is Vi's bread and butter. Try:

:g/attributeA/ copy . | s//attributeB/g

where

:g/pattern/ command1 | command2 | ...

executes commands on each line matching pattern (see :help :global),

copy .

copies the current line (see :help :copy) matched by :g to after the address . (meaning the current line), and

s/pattern/replacement/g

then performs a substitution on the current line (see :help :substitute), i.e. the copy you just made. The g flag at the end causes the substitution to be performed for all matching patterns in the line, not just the first. Also note that I left the search pattern empty: Vim will remember the last search pattern used in the previous :global or :substitute command as a convenience.



回答2:

Your exact sample is easy to achieve with:

yy
p
:s/A/B/g

But it is entirely possible that you want something more generic. If that's the case you should probably edit your question.



回答3:

Have a look at this function:

function AddAttribute()
    exe "/this.attributeA=attributeA;"
    exe "normal yyp"
    exe "s/attributeA/" . input('New attribute: ') . "/g"
endfunction

When you call the function call AddAttribute() you will be prompted for a new attribute which will be added like in your example. You can bind a key for this with something like :map <F5> :call AddAttribute<CR> so you just hit F5 in order to add this line.

Edit

If you want to duplicate all lines with attributeA (which doesn't make sense to me), you could do that with this mapping (^M is CTRL+v and then Enter):

:map <F5> :call inputsave()\|let newAttribute=input('new attribute: ')\|:call inputrestore()\|:g/attributeA/exe "normal! yyp"\|exe ":s/attributeA/" . newAttribute . "/g"^M

When you hit F5 you are prompted for a new attribute and alle lines containing attributeA are duplicated and substituted with your input.



标签: vim vi