Vi and Vim Asked on February 6, 2021
I got this sed regex I found:
sed '/start/!d;s//&n/;s/.*n//;:a;/end/bb;$!{n;ba};:b;s//n&/;P;D'
which basically outputs the content that is between a starting point and an end point.
##1##
this is a test
with multiple
line
##z##
and replacing start
with ##1##
, and end
to ##z##
would give:
this is a test
with multiple
line
If there are multiple occurrences of the ##1##
and ##z##
, then it would obviously show all the in-between text of said occurrence, like so:
##1##
this is a test
with multiple
line
##z##
##1##
this is a test
with multiple
line
##z##
to
this is a test
with multiple
line
this is a test
with multiple
line
To clarify even more:
##1##
this is a test
with multiple
line
##z##
##2##
test
##z##
would obviously give only what is specified as starting point (since the ending point ##z##
is always the same).
So if i use ##2##
instead as starting point:
test
This would give the above as output.
My goal is to convert this to a compatible regex for vim.
I’m using this site and the local manual as help but, I’m unsure where to start for converting the above to vim regex.
Just for fun, remember you can always do
:%!sed '/start/!d;s//&n/;s/.*n//;:a;/end/bb;$!{n;ba};:b;s//n&/;P;D'
And that’s still “vim” :P
Answered by D. Ben Knoble on February 6, 2021
:g/END|%^/,/START|%$/s/.*//
This global command marks all lines matching END
or the beginning of file (%^
). Then it proceeds to delete everything from the marked lines up to START
or the end of file (%$
) by using the substitution command s/.*//
.
A side-by-side example:
Before |After
________________________________
test |
START |
this is a test |this is a test
with multiple |with multiple
line |line
END |
0 |
START |
0101 |0101
END |
11 |
111 |
If you don't want the blank lines, you can replace s/.*//
by d
in the global command.
Answered by Quasímodo on February 6, 2021
An extremely simple function which does the job far more idiomatically:
function! Between(start, end) abort
let [start_line, _] = searchpairpos(a:start, '', a:end, 'bWn')
let [end_line, _] = searchpairpos(a:start, '', a:end, 'Wn')
if start_line is# 0 || end_line is# 0
return
endif
call setline(start_line, '') " or: execute start_line 'delete'
call setline(end_line, '') " or: execute end_line 'delete'
endfunction
Name it whatever you want, and then do, e.g.,
call Between('##1##', '##z##')
(which you could bind to a key, perhaps).
To work on the whole file, you might be able to use :global
(or even just :%call Between(...)
), or you may need a loop wrapping this function and traversing the file. In the case of the latter, I would use search(a:start)
to find the next start and then +
to be inside the nested region; then I would call the function. This is faster than calling the function on every line.
Answered by D. Ben Knoble on February 6, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP