Regex matching the first occurrence of a string

512 views
Skip to first unread message

ShayAllen

unread,
May 28, 2010, 10:50:48 PM5/28/10
to vim...@googlegroups.com

I want to match everything between and including Begin and End. There are
several blocks in the file:

Begin
ssss
dfsdfsdf
sdfsdf
End

Begin
sasdfsa
sdfgsd
hghfgh
End

My best guess so far:
:%s/Begin\_.*\(End\)\{-1}/This was one block/
Doesn't work

What am I missing?
Thanks.
--
View this message in context: http://old.nabble.com/Regex-matching-the-first-occurrence-of-a-string-tp28712875p28712875.html
Sent from the Vim - General mailing list archive at Nabble.com.

Stahlman Family

unread,
May 29, 2010, 7:35:16 AM5/29/10
to vim...@googlegroups.com

ShayAllen wrote:
> I want to match everything between and including Begin and End. There are
> several blocks in the file:
>
> Begin
> ssss
> dfsdfsdf
> sdfsdf
> End
>
> Begin
> sasdfsa
> sdfgsd
> hghfgh
> End
>
> My best guess so far:
> :%s/Begin\_.*\(End\)\{-1}/This was one block/

Try this...
%s/^Begin\_$\_.\{-}\_^End$/This was one block/

:help /\{
:help /\_$
:help /\_^

Note that in your pattern, the \{-1} was modifying "End", which I don't
think is what you wanted.

Brett Stahlman

Tim Chase

unread,
May 29, 2010, 7:25:37 AM5/29/10
to vim...@googlegroups.com, ShayAllen
On 05/28/2010 09:50 PM, ShayAllen wrote:
>
> I want to match everything between and including Begin and End. There are
> several blocks in the file:
>
> Begin
> ssss
> dfsdfsdf
> sdfsdf
> End
>
> Begin
> sasdfsa
> sdfgsd
> hghfgh
> End
>
> My best guess so far:
> :%s/Begin\_.*\(End\)\{-1}/This was one block/
> Doesn't work

Without details of what "Doesn't work" means, it's a little hard
to guess. Can your blocks be nested?

Begin
stuff
Begin
stuff2
stuff3
End
stuff4
End

Does case matter? Can you have begin/end text in other stuff?

Begin
stuff
this is not the End
more stuff
End

-tim


Ben Fritz

unread,
May 30, 2010, 11:02:17 PM5/30/10
to vim_use


On May 28, 9:50 pm, ShayAllen <alexalle...@hotmail.com> wrote:
> I want to match everything between and including Begin and End. There are
> several blocks in the file:
>
> Begin
>   ssss
>   dfsdfsdf
>   sdfsdf
> End
>
> Begin
>   sasdfsa
>   sdfgsd
>   hghfgh
> End
>
> My best guess so far:
> :%s/Begin\_.*\(End\)\{-1}/This was one block/
> Doesn't work
>

One problem you have is that you use the "greedy" match, \_.*, so that
you will match everything between the FIRST begin and the LAST end.

Try using \_.\{-} instead, to match in a "non-greedy" fashion, so that
you only get the individual blocks.

From your title, I infer that you may want to match only the very
first block in the file. The easiest way to do this is probably just
to add the 'c' flag to the end of your substitute command, so that you
need to "confirm" each replacement (you could then cancel the
substitute after the first replacement).

So, your final command would be:

:%s/Begin\_.*\(End\)\{-1}/This was one block/c

Ben Fritz

unread,
May 30, 2010, 11:02:56 PM5/30/10
to vim_use


On May 30, 10:02 pm, Ben Fritz <fritzophre...@gmail.com> wrote:
>
> So, your final command would be:
>
> :%s/Begin\_.*\(End\)\{-1}/This was one block/c

Oops,

:%s/Begin\_.\{-}\(End\)\{-1}/This was one block/c

ShayAllen

unread,
May 30, 2010, 9:09:07 PM5/30/10
to vim...@googlegroups.com


ShayAllen wrote:
>
> I want to match everything between and including Begin and End. There are
> several blocks in the file:
>
> Begin
> ssss
> dfsdfsdf
> sdfsdf
> End
>
> Begin
> sasdfsa
> sdfgsd
> hghfgh
> End
>
> My best guess so far:
> :%s/Begin\_.*\(End\)\{-1}/This was one block/
> Doesn't work
>
> What am I missing?
> Thanks.
>

Fair questions, Tim. No nested blocks or other tricky stuff. Brett's
solution worked fine and was an instructive example for me. Thanks.

--
View this message in context: http://old.nabble.com/Regex-matching-the-first-occurrence-of-a-string-tp28712875p28725924.html

Reply all
Reply to author
Forward
0 new messages