Reemplazar texto de la línea de arriba en Vim
Pregunta
¿Cómo puedo reemplazar los primeros diez caracteres de una línea donde esos diez caracteres coinciden con un patrón particular con los primeros diez caracteres de la línea de arriba?
Editar: no estaba claro si estaba pidiendo reemplazar los primeros diez caracteres donde la coincidencia podría aparecer en cualquier lugar dentro de la línea, así que tal vez tome nota en su respuesta si se trata de este caso (llame a este caso B y el caso previsto A?)
Solución
Prehaps:
:%s/^\(.\{10}\)\(.*\n\)abcdefghij\(.*\)/\1\2\1\3/
Donde 'abcdefghij' es la cadena de 10 caracteres en la segunda línea
Otros consejos
Algo como esto funcionaría:
%s/^.\{10\}/\=strpart(get(getbufline("", line(".")-1), 0, ""), 0, 10)/
donde ^. \ {10 \}
es su patrón real.
%s/ # substitute all lines matching…
^.\{10\} # your pattern
/ # …with…
\= # an expression:
strpart( # gets the part of a string
get( # gets an element of a list
getbufline( # gets a list of lines from the current buffer
"", line(".")-1) # getbufline() the line before the current line
, 0, "") # get() first line in buffer, default to ""
, 0, 10) # strpart() first ten characters
/ # …end of substitution
:2,$g/<pattern>/s/^.\{10}/\=strpart(getline(line(".")-1),0,10)
-
2, $
es nuestro rango (ya que la primera línea no tiene línea anterior) -
g //
le permite ejecutar un comando en líneas que coinciden con un patrón determinado. -
s / ^. \ {10} /
reemplazará los primeros 10 caracteres de una línea -
\ =
le permite sustituir el resultado de una expresión vim en un:s//
-
line (". ")
es el número de línea actual -
getline (line (". ") - 1)
es el texto de la línea anterior -
strpart (getline (line (". ") - 1), 0,10)
son los primeros 10 caracteres de la línea anterior
Por ejemplo 2, $ g / frog / s / ^. \ {10} / \ = strpart (getline (line (". ") - 1), 0,10)
cambiará:
I like eating mangos before frying frogs legs I wish I had a puppy She gave Dad a frog
A esto:
I like eating mangos I like eating frogs legs I wish I had a puppy I wish I had a frog
Si tengo una acción compleja como esa, generalmente grabo una macro usando el comando q
. Algo así (no probado):
/<pattern>
qq
10x
k
10yl
j
P
n
q
Y luego, repetidamente, emita esa macro como @q
opcionalmente prefijada con un conteo.
Puede usar buscar y reemplazar:
:7,9 s/foo/bar/c
Este ejemplo busca de la línea 7 a la 9 para cada aparición de 'foo', y lo reemplaza con 'barra', solicitando una confirmación en cada golpe. Si no desea confirmar, suelte la c al final. Elija el rango como mejor le parezca y esto lo llevará a donde quiera
Usando solo los movimientos de vim y tirando / pegando .. Dado el contenido del archivo de ...
1234567890abcdef
qwertyuiopasdfgh
Con el cursor en q, 10x
, el archivo se convierte en:
1234567890abcdef
asdfgh
Mueve el cursor a la primera línea (usando k
lo hará), luego haz 10yl
(tira 10 caracteres, a la derecha)
Luego retroceda una línea, j
, y pegue P
(mayúscula, para pegar debajo del cursor) y el archivo se convertirá en:
1234567890abcdef
1234567890asdfgh
En resumen, comenzando con el cursor en q:
10xk10yljP
..que puede pegar o asignar a una macro
Sería más corto si hubiera un atajo obvio para pegar sobrescribiendo, pero no pude encontrar tal cosa
Otra opción es una búsqueda / reemplazo de expresiones regulares de aspecto increíblemente oscuro.
Visual-line selecciona las dos líneas de destino y ejecuta la siguiente búsqueda y reemplazo:
:'<,'>s/\(\(.\{10\}\).*\)\n\(.\{10\}\)\(.*\)$/\1\r\2\4/
Básicamente agarra ..
-
\ 1
: toda la primera línea -
\ 2
- los primeros 10 caracteres (en un grupo anidado) - un salto de línea
-
\ 3
: los primeros diez caracteres de la línea dos -
\ 4
- el resto de la segunda línea
Luego construye las dos líneas como \ 1 \ n \ 2 \ 4
- completa la primera línea, salto de línea, primeros 10 caracteres de la primera, resto de la segunda