VIM ¿Reemplazar palabra con el contenido del búfer de pegado?

110

Necesito hacer un montón de reemplazos de palabras en un archivo y quiero hacerlo con un comando vi, no con un comando EX como :%s///g. Sé que esta es la forma típica en que se reemplaza la palabra en la posición actual del cursor: cw<text><esc>pero ¿hay alguna manera de hacer esto con el contenido del registro sin nombre como texto de reemplazo y sin sobrescribir el registro?

plong
fuente
8
RESOLUCIÓN: Para mi necesidad inmediata, solía 12yltirar de 12 caracteres y "_cw^r0reemplazar una palabra. Luego pude usar el .comando para repetir el reemplazo en todo el archivo.
Plong

Respuestas:

127

Estoy pensando que por "pegar" te refieres al registro sin nombre (tirar / poner / cambiar / eliminar / sustituir), ¿verdad? (Dado que ese es el que se sobrescribirá con el comando de cambio).

Los registros generalmente se especifican escribiendo "luego el nombre (carácter único) del registro, como "ayluego "aptirar en el registro a, luego poner el contenido del registro a. Lo mismo ocurre con un comando de cambio. En este caso, si no desea que el texto que elimina con el comando de cambio vaya a ninguna parte, puede usar el registro de agujero negro"_ : "_cw. Luego, una vez en el modo de inserción, puede presionar ctrl-R seguido del registro que desea (probablemente ") poner en el contenido de ese registro.

  • "* - registro de selección (pegar botón central)
  • "+ - registro del portapapeles (probablemente también accesible con ctrl-shift-v a través de la terminal)
  • "" - Registro de yank / put / change / delete / substitute predeterminado de vim (sin nombre).

Respuesta corta: "_cw^R"

Editar: como sugieren otros, por supuesto, puede usar un registro diferente para el tirón (o lo que sea) que llevó su texto al registro predeterminado. Sin embargo, no siempre piensas en eso primero, por lo que es bueno hacer un solo comando de cambio sin desperdiciarlo. Aunque no está totalmente impresionado. Están los registros numerados a "0través de"9 :

Vim llena estos registros con texto de los comandos yank y delete.

El registro numerado 0 contiene el texto del comando yank más reciente, a menos que el comando especifique otro registro con ["x].

El registro numerado 1 contiene el texto eliminado por el comando de eliminación o cambio más reciente, a menos que el comando especifique otro registro o el texto tenga menos de una línea (entonces se usa el registro de eliminación pequeño). Se hace una excepción para el operador delete con estos comandos de movimiento: %, (, ), `, /, ?, n, N, {y }. El registro "1 siempre se usa entonces (esto es compatible con Vi). El registro" - se usa también si la eliminación está dentro de una línea.

Con cada eliminación o cambio sucesivo, Vim cambia el contenido anterior del registro 1 al registro 2, 2 al 3, y así sucesivamente, perdiendo el contenido anterior del registro 9.

Cascabel
fuente
1
De acuerdo, ¿crees que ya he copiado suficientes documentos de los registros en mi respuesta? Todo está ahí debajo :help registers.
Cascabel
48

Usando la información de esta publicación, he creado este útil mapeo. Elegí "cp" porque significa "cambiar pegar"

nmap <silent> cp "_cw<C-R>"<Esc>

EDITAR:

También di un paso más allá y apoyé cualquier moción.

Para obtener el equivalente del comando anterior, sería cpwpara "cambiar palabra de pegar"

"This allows for change paste motion cp{motion}
nmap <silent> cp :set opfunc=ChangePaste<CR>g@
function! ChangePaste(type, ...)
    silent exe "normal! `[v`]\"_c"
    silent exe "normal! p"
endfunction
ostler.c
fuente
El <silent> hace que no funcione para mí ... ¿alguna idea de por qué sería eso? Soy un n00b en mapeos y funciones.
Hollister
El único problema con esto es que no puede elegir un registro para pegar ... pero en ese caso, supongo que podría simplemente cw y usar CTRL + R
Steve Vermeulen
2
Puede haber una mejor manera de agregar nombres de registros, pero lo siguiente funciona para mí: nmap <silent> cp :let g:currentRegister=v:register<cr>:set opfunc=ChangePaste<CR>g@ function! ChangePaste(type, ...) silent exe "normal! `[v`]\"_c".getreg(g:currentRegister) endfunction
Steve Vermeulen
@eventualEntropy esto funciona bien para reemplazar líneas, ¿cómo puedo hacer que esto funcione para palabras en lugar de líneas? Todavía estoy aprendiendo vim. Gracias por la ayuda.
Xavitoj Cheema
@XavitojCheema Ni siquiera recuerdo haber hecho ese comentario, jaja. Pero resulta que desde entonces escribí un complemento para proporcionar esta funcionalidad ( github.com/svermeulen/vim-easyclip )
Steve Vermeulen
27

Puede usar el modo visual de vim para esto. por ejemplo, copiar una palabra: yey luego sobrescribir otra con la palabra copiada:vep

Ste
fuente
9
Esto funciona, pero también debe tenerse en cuenta que el pegado visual sobrescribe el búfer de tirón para el texto recién eliminado.
ostler.c
24

Si su cursor está en la palabra que desea reemplazar con el contenido del registro sin nombre, puede usar viwp. vcambia al modo visual, iwselecciona la palabra interna yp coloca el contenido del registro en su lugar.

En la práctica, cuando necesito reemplazar una palabra (nombre de la función, etc.) por otra, pasaré a la que usaré como reemplazo, yiwpara tirar de la palabra interna al registro sin nombre, luego pasaré a la palabra I ' m reemplazando, yviwp reemplazarlo. Una forma bastante rápida de sustituir una palabra por otra. Si buscó ( /) la palabra que está reemplazando para acceder a ella, puede presionar npara ir a la siguiente aparición que necesita reemplazar. Obviamente, no sustituye al uso :%s/find/replace/g, pero para un par de sustituciones rápidas puede ser útil, especialmente si ya tiene la nueva palabra en un registro.

Travis Northcutt
fuente
4
Me sorprende que esta no sea la solución aceptada: todo lo anterior, aunque es más flexible en algunos casos extremos, es mucho más detallado para simplemente 'intercambiar el registro actual sin nombre por una selección en algún lugar', que es la situación original asker vino aquí.
ELLIOTTCABLE
1
Esto es muy útil e intuitivo.
lacostenycoder
6

Si hace uso de un registro con nombre (es decir, use "ayo "ad, etc., para llenar su registro de pegado), puede hacer algo como

cw<CTRL-R>a<esc>

Que sustituirá la palabra por el contenido del registro a. Por lo que puedo decir, no puede usar el registro predeterminado porque cuando lo haga cwse completará con la palabra que fue cortada por ese comando.

Daniel Vandersluis
fuente
¡Puede usar el registro predeterminado! Mira mi respuesta.
Cascabel
2

¿Te refieres al búfer de pegado del sistema o al registro vi?

Si desea utilizar el búfer de pegado del sistema, está bien y podría hacerlo dw"+P: "elija un registro y"+ es el búfer de pegado del sistema.

De lo contrario, copie en el registro no predeterminado con decir "aypara copiar en el registro ay luego para reemplazar algo hacerdw"aP

Hamish Downer
fuente
Gracias, Hamish. Intenté eso, pero dwelimina los espacios en blanco finales después de lo que consideraría la "palabra", mientras que cwsolo cambia la palabra. Por esa razón, dwno funcionará para mí.
Plong
En ese caso, dedebería funcionar para usted: se eliminará hasta el final de esta palabra, mientras que dwse eliminará al principio de la siguiente.
Hamish Downer
1

Puede usar ywpara tirar de la palabra, luego puede cambiar la palabra con la palabra tirada por vipwpara tirar de la palabra y pegar la palabra previamente tirada.

YevgenyYork
fuente
0

Puedes usar registros para eso:

primer lugar texto de reemplazo en el registro <mark some text>"ay

dónde a esta el nombre del registro

entonces puedes usar ese registro en reemplazo

ve"ap

lollinus
fuente
Desafortunadamente, no pude simplemente repetir la última operación de pegar vía ., que es otra cosa que quería hacer. Pero gracias. Muy apreciado.
Plong
0

O puede hacer Shift+ v- p(seleccione la línea completa y pegue en su lugar)

elimirks
fuente
1
o pdw ... ¿No amas a vim? : P
elimirks