Replace text from line above in Vim
How do I replace the first ten characters of a string where those ten characters match a specific pattern with the first ten characters from the string above?
Edit: It's unclear if I am asking to replace the first ten characters where the match could appear anywhere in the string, so maybe take a note in your answer if it deals with this case (call this case B and the supposed one case A?)
a source to share
Something like this will work:
%s/^.\{10\}/\=strpart(get(getbufline("", line(".")-1), 0, ""), 0, 10)/
where ^.\{10\}
is your actual template.
%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
a source to share
:2,$g/<pattern>/s/^.\{10}/\=strpart(getline(line(".")-1),0,10)
-
2,$
- our range (since the first line has no previous line) -
g//
allows you to run a command on lines that match a given pattern. -
s/^.\{10}/
will replace the first 10 characters of the string -
\=
allows you to substitute the result of a vim expression in:s//
-
line(".")
- current line number -
getline(line(".")-1)
is the text of the previous line -
strpart(getline(line(".")-1),0,10)
is the first 10 characters of the previous line
For example, 2,$g/frog/s/^.\{10}/\=strpart(getline(line(".")-1),0,10)
will change:
I like eat ing mangos before fry ing frogs legs I wish I h ad a puppy She gave D ad a frog
For this:
I like eat ing mangos I like eat ing frogs legs I wish I h ad a puppy I wish I h ad a frog
a source to share
You can use search and replace:
:7,9 s/foo/bar/c
This example searches lines 7 through 9 for each case of "foo" and replaces it with "bar", asking for confirmation on each hit. If you don't want to confirm, leave a c at the end. Choose the range as you see fit and this should get you where you want
a source to share
Using only vim movements and yanking / inserting .. Given the contents of the file ..
1234567890abcdef qwertyuiopasdfgh
With the cursor on q,, the 10x
file becomes:
1234567890abcdef asdfgh
Move cursor to first line (with k
do this) then do 10yl
(check 10 characters, right)
Then go back one line j
and paste P
(uppercase to paste under the cursor) and the file becomes:
1234567890abcdef 1234567890asdfgh
In short, starting at the cursor at q:
10xk10yljP
.. which you can insert, or assign to a macro
It would be shorter if there was an explicit shortcut to insert by overwrite, but I couldn't find such a thing
Another option is the incredibly stealthy regex search / replace.
The visual bar selects two target lines and triggers the following search and replace:
:'<,'>s/\(\(.\{10\}\).*\)\n\(.\{10\}\)\(.*\)$/\1\r\2\4/
Basically it is exciting.
-
\1
- the entire first line -
\2
- first 10 characters (in a nested group) - linebreak
-
\3
- the first ten characters of the second line -
\4
- the rest of the second line
Then it constructs two lines as \1\n\2\4
- complete first line, line, first 10 characters of the first, the rest of the second
a source to share