Delete lines matching hits

166 views
Skip to first unread message

Eduard

unread,
Feb 5, 2011, 1:14:19 PM2/5/11
to vim_use
Hi there!

I make abundant use of a wonderful function I found at

http://vim.wikia.com/wiki/Copy_the_search_results_into_clipboard

to copy all matching lines, whole lines, containing hits.

I wonder if there's a way to do the same but instead of copying them
to the clipboard, delete them.

I very much appreciate your attention,

Eduard Fabra
http://www.google.com/profiles/edfabra

PS. The exact script I'm using is this:

" Use /pattern to search for something, then
" :call CopyMatchingLines()
" to copy all lines containing hits (whole lines).
" The pattern may extend over multiple lines.
" The 'normal! $' attempts to avoid copying the same line more than
once.
" BUG: For some patterns, it could miss a second hit?
function! CopyMatchingLines()
let posinit = getpos(".")
call cursor(1, 1)
let cnt = 0
let hits = []
let snum = search(@/, 'cW')
while snum > 0
let enum = search(@/, 'ceW')
call extend(hits, getline(snum, enum))
let cnt += 1
normal! $
let snum = search(@/, 'W')
endwhile
if cnt > 0
let @+ = join(hits, "\n") . "\n"
endif
call cursor(posinit[1], posinit[2])
echomsg cnt 'lines (or blocks) were appended to the clipboard.'
endfunction

Javier Rojas

unread,
Feb 5, 2011, 1:25:02 PM2/5/11
to vim...@googlegroups.com
On Sat, Feb 05, 2011 at 10:14:19AM -0800, Eduard wrote:
> ...

> to copy all matching lines, whole lines, containing hits.
>
> I wonder if there's a way to do the same but instead of copying them
> to the clipboard, delete them.

:g/pattern/d

See :help :g

--
Javier Rojas

GPG Key ID: 0x24E00D68

signature.asc

Eduard

unread,
Feb 5, 2011, 1:49:18 PM2/5/11
to vim...@googlegroups.com
Oh my god! :-) So easy and I missed it altogether.

Thank you Javier!

Ben Fritz

unread,
Feb 5, 2011, 6:02:08 PM2/5/11
to vim_use


On Feb 5, 12:25 pm, Javier Rojas <jeroja...@devnull.li> wrote:
> On Sat, Feb 05, 2011 at 10:14:19AM -0800, Eduard wrote:
> > ...
> > to copy all matching lines, whole lines, containing hits.
>
> > I wonder if there's a way to do the same but instead of copying them
> > to the clipboard, delete them.
>
> :g/pattern/d
>
> See :help :g
>

I think this will not work for the second part claimed by the comment
in the code posted: "The pattern may extend over multiple lines."

For example,

abc
def
ghi

:g/abcc\ndef/d

will delete only "abc", it will not delete "def".

I'm not sure how important this is to the OP...

Tim Chase

unread,
Feb 5, 2011, 6:48:53 PM2/5/11
to vim...@googlegroups.com, Ben Fritz
On 02/05/2011 05:02 PM, Ben Fritz wrote:
>>> I wonder if there's a way to do the same but instead of copying them
>>> to the clipboard, delete them.
>>
>> :g/pattern/d
>
> I think this will not work for the second part claimed by the comment
> in the code posted: "The pattern may extend over multiple lines."
>
> For example,
>
> abc
> def
> ghi
>
> :g/abcc\ndef/d
>
> will delete only "abc", it will not delete "def".
>
> I'm not sure how important this is to the OP...

If it is, it should be fairly possible to do it with a :s
command, something like

:%s/^abc\ndef\n//

-tim

ZyX

unread,
Feb 5, 2011, 8:00:54 PM2/5/11
to vim...@googlegroups.com
Reply to message «Re: Delete lines matching hits»,
sent 02:48:53 06 February 2011, Sunday
by Tim Chase:

> If it is, it should be fairly possible to do it with a :s
> command, something like
>
> :%s/^abc\ndef\n//

It should be
:%s/.*{pattern}.*\n//
or, in this particular case:
:%s/.*abc\ndef.*\n//
because we are going to delete the whole lines that contain match, but nobody
said that they contain only match. Both solutions does not work for patterns
with \zs and \ze, maybe it is better to do the following:

function! s:MarkToDel(todelete, sline, submatch)
let lnum=len(substitute(a:submatch, '\n\@!.', '', 'g'))
call add(a:todelete, [a:sline, lnum])
return a:submatch
endfunction
function! DeleteMatchingLines(pattern)
let todelete=[]
let savedgdefault=&gdefault
set nogdefault
try
execute '%s/'.escape(a:pattern, '/').
\'/\=s:MarkToDel(todelete, line("."), submatch(0))'
finally
let &gdefault=savedgdefault
endtry
let deleted=0
for [sline, lnum] in todelete
let sline-=deleted
let deleted+=lnum+1
let range=sline.','.(sline+lnum)
execute range.'delete _'
endfor
endfunction

By the way, with some trivial modifications this code can be used in
CopyMatchingLines because it has the following advantages:
1. For each match only one search is done.
2. Pattern is compiled only once.
3. No «The 'normal! $' attempts to avoid copying the same line more than
once.»: vim does this for you when you omit /g flag (this is why 'gdefault'
option is saved and restored).

Original message:

signature.asc

Eduard

unread,
Feb 6, 2011, 11:45:16 AM2/6/11
to vim...@googlegroups.com
Hi Ben,

On Sunday, February 6, 2011 12:02:08 AM UTC+1, Ben Fritz wrote:

I think this will not work for the second part claimed by the comment
in the code posted: "The pattern may extend over multiple lines."

For example,

abc
def
ghi

:g/abcc\ndef/d

will delete only "abc", it will not delete "def".

True! :-(
 

I'm not sure how important this is to the OP...

Very important :-)

The Kindle stores all book clippings in a text file, in this typical way:

==BEGIN QUOTING FROM KINDLE==

The Curse of the Self: Self-Awareness, Egotism, and the Quality of Human Life (Mark R. Leary)
- Highlight Loc. 21 | Added on Tuesday, November 23, 2010, 08:10 PM

The  inherently egocentric and egotistical manner in which the self processes  information can blind people to their own shortcomings and undermine  their relationships with others.

==========
The Curse of the Self: Self-Awareness, Egotism, and the Quality of Human Life (Mark R. Leary)
- Highlight Loc. 24 | Added on Tuesday, November 23, 2010, 08:11 PM

And, ironically, using self-reflection to  help us deliberately control our own behavior can often backfire and create   more problems than it solves.

==========
Capitalism (Ayn Rand)
- Highlight Loc. 9-10 | Added on Wednesday, December 22, 2010, 08:24 PM

I want to stress that our primary interest is not politics or economics as such, but "man's nature and man's relationship to existence"—and that we advocate capitalism because it is the only system geared to the life of a rational being.

==========
The Curse of the Self: Self-Awareness, Egotism, and the Quality of Human Life (Mark R. Leary)
- Highlight Loc. 27-28 | Added on Tuesday, November 23, 2010, 10:24 PM

This book will explain how and why our natural tendency to talk to  ourselves, see the world egocentrically, defend our egos, seek self-validation,   and engage in other acts of selfhood often works against our best  interests.

==========

==END QUOTING FROM KINDLE==

With the 'CopyMatchingLines' function I've reported before, I can easily collect all the citations belonging to the book I've just read, and copy them to an independent text file. What I'd like to do next is delete them from the original kindle text. I was happy with Javier's suggestion but, as you indicate, it only deletes the first line. 

I'm going to try Tim's and Zyx's approach.

Thank you very much to all four!

Eduard

unread,
Feb 6, 2011, 11:50:20 AM2/6/11
to vim...@googlegroups.com
Hy ZyX!
How should I use your function? I've copied it to my .vimrc but don't know what to do next :-) 

Thank you again for your time (and Tim's too!)

-- 
Eduard.

ZyX

unread,
Feb 6, 2011, 12:25:34 PM2/6/11
to vim...@googlegroups.com
Reply to message «Re: Delete lines matching hits»,
sent 19:50:20 06 February 2011, Sunday
by Eduard:

> How should I use your function? I've copied it to my .vimrc but don't know

> what to do next :-)-
I thought that the only argument to this function is self-explanatory. Just do
:call DeleteMatchingLines('abc\ndef')<CR>
to delete all lines matching pattern `abc\ndef' (they are not put in any
register).

Original message:

signature.asc

Eduard Fabra

unread,
Feb 6, 2011, 12:53:05 PM2/6/11
to vim...@googlegroups.com
Thank you ZyX!

On Sun, Feb 6, 2011 at 18:25, ZyX <zyx...@gmail.com> wrote:

> > How should I use your function? I've copied it to my .vimrc but don't know
> > what to do next :-)-
> I thought that the only argument to this function is self-explanatory. Just do
>    :call DeleteMatchingLines('abc\ndef')<CR>
> to delete all lines matching pattern `abc\ndef' (they are not put in any
> register).

--
Eduard.
http://www.google.com/profiles/edfabra

Reply all
Reply to author
Forward
0 new messages