Re: how can you delete every line between two phrases?

1,014 views
Skip to first unread message

Salman Halim

unread,
Nov 16, 2012, 10:01:56 PM11/16/12
to Vim Users
On Fri, Nov 16, 2012 at 7:35 PM, Ant <antho...@gmail.com> wrote:
Hello all,

I am starting to see the power of VIM! But I am still so new at it all so would like some help.

I am trying to do something, here is an example

==============================
Extremely large document.txt
hello little cat.
how are you?
I hope you
are
well today.
:)
Hello world!
==============================

how would you delete every line in between "how are you?" and ":)"??

is there an easy way to do it for several hundred text documents? An example of my use is deleting text between two unique numbers that occur on hundreds of text documents, and have different content in each. Actually I wouldnt mind being able to get all that content out onto another text file.

THANKS!!


The deletion command:

:/^how are you?$/+1,/^:)$/-1d

This defines a range starting with the line immediately after the line matching "^how are you?$" (that's the +1) and just before the line matching "^:)$" (the -1 bit) and deletes it using the "d" command. If you wanted to delete the two matching lines, also, then you would leave out the offsets.

Bear in mind that this works just like the standard search command (/) and works on the next matching range after the cursor; if you have multiple matches in one file, stick a g before the whole thing (:g/^how...).

While Vim is an editor and not meant to handle multiple files in this fashion, in my opinion, you could probably use :bufdo, :argdo, :windo or :tabdo (most likely argdo) to make it happen across a number of files.

I wonder if sed might be better for this task; the syntax for the command would probably be similar.

Hope this helps,

Salman

Tony Mechelynck

unread,
Nov 16, 2012, 10:22:22 PM11/16/12
to vim...@googlegroups.com, Salman Halim
The above implements a linewise deletion. For characterwise, you can use

:%s/how are you?\zs\_.*\ze:-)//e

Notes:
- If there are several matching pairs, this subsitute will remove from
the first "how are you" to the last ":-)".
- The above is for "exclusive" deletion (keeping the bounding strings).
For "inclusive", remove the \zs and \ze markers
- The /e flag at the end avoids an error if there is no match.


Best regards,
Tony.
--
Hall's Laws of Politics:
(1) The voters want fewer taxes and more spending.
(2) Citizens want honest politicians until they want something
fixed.
(3) Constituency drives out consistency (i.e., liberals defend
military spending, and conservatives social spending in
their own districts).


Tim Chase

unread,
Nov 16, 2012, 11:00:38 PM11/16/12
to vim...@googlegroups.com, Tony Mechelynck, Salman Halim
On 11/16/12 21:22, Tony Mechelynck wrote:
> The above implements a linewise deletion. For characterwise, you can use
>
> :%s/how are you?\zs\_.*\ze:-)//e
>
> Notes:
> - If there are several matching pairs, this subsitute will remove from
> the first "how are you" to the last ":-)".

Which you can then tweak by changing the "*" to "\{-}"

If you want to do it line-wise and you have multiple instances in
the file, you can do something like

:g/how are you?/.;/:-)/d

to delete them inclusive, or

:g/how are you?/+;/:-)/-d

(the "+" bumps the starting line forward one from the match, the "-"
bumps it back one line from the ending match).

And if you have multiple files to do it across, you can use
windo/bufdo/argdo/tabdo to prefix the command (either setting
'hidden' beforehand or writing the file as well)

-tim


Tim Chase

unread,
Dec 2, 2012, 9:39:38 PM12/2/12
to Jiaxing Wang, vim...@googlegroups.com
On 12/02/12 20:15, Jiaxing Wang wrote:
> In :g/how are you?/.;/:-)/d,
> Is '/how are you?/.;/:-)/' the pattern in
> :[range]g[lobal]/{pattern}/[cmd]?
> Would you mind explaining this pattern a little? I don't quite
> understand this, thanks.

Using your template of ":[range]global]/{pattern}/[cmd]" it breaks
down as

:g/how are you?/[cmd]

where [cmd] is

.;/:-)/d

which is a range from the currently matching "how are you?" line
through the next line containing ":-)". The Ex command issued over
that range is "d"elete. If you read at

:help :range

you'll see the "/" is a way of specifying an address. You can even
stack them if you want, such as

+3;/hello/?world?+2

which will start the range 3 lines after the currently matching
line, and end the range at the location found by searching forwards
to "hello", then backwards to "world", and then going forwards two
lines. It's a bit of a crazy example, but sometimes that's exactly
what you need to specify the range you want. A recent real-world
example from my own use was something like:

:g/^\s*def [^(]*[pP]rovider/+1;'}?DEBUG?s/^/#

which commented out ("s/^/#") the lines in Python code after the
function definition, through the last DEBUG in the current paragraph
(as marked by '}).

The difference between using ";" (as I do) and using "," is one of
those things I don't fully grasp as it seems to be fairly
interchangeable in other contexts. But in this use-case as a
destination for :g commands, I find that I almost always want ";".
This is tersely documented at

:help :;

I hope that helps disassemble my answer so that you can go do crazy
things with vim and impress your colleagues, too. :-)

-tim



Jiaxing Wang

unread,
Dec 2, 2012, 9:15:50 PM12/2/12
to vim...@googlegroups.com, Tony Mechelynck, Salman Halim, Tim Chase
Hi,tim

stosss

unread,
Dec 2, 2012, 9:46:19 PM12/2/12
to vim...@googlegroups.com
I looked at :help :range as Tim suggested above. Just want to see if I
understand correctly. Does vim do addressing like sed? That seems to
be what I see.

Tim Chase

unread,
Dec 2, 2012, 10:43:21 PM12/2/12
to vim...@googlegroups.com, stosss
On 12/02/12 20:46, stosss wrote:
> On Sun, Dec 2, 2012 at 9:39 PM, Tim Chase <v...@tim.thechases.com> wrote:
>> On 12/02/12 20:15, Jiaxing Wang wrote:
>>> In :g/how are you?/.;/:-)/d,
>>> Is '/how are you?/.;/:-)/' the pattern in
>>> :[range]g[lobal]/{pattern}/[cmd]?
>>> Would you mind explaining this pattern a little? I don't quite
>>> understand this, thanks.
>>
>> [snip my rambling about ranges]
>
> I looked at :help :range as Tim suggested above. Just want to see if I
> understand correctly. Does vim do addressing like sed? That seems to
> be what I see.

Yes, only better. Sed has a difficult time going backwards (you
have to gather things up in the hold space or in the current
buffer). Vim has no problems marching all over your document, so
you can use marks, relative & absolute line numbering, searching
forwards and backwards, or any chain of those you want in any order
that suits your needs.

-tim




Reply all
Reply to author
Forward
0 new messages