[prev in list] [next in list] [prev in thread] [next in thread]
List: perl-beginners
Subject: Re: Regex one-liner to find several multi-line blocks of text in a single file
From: Jim Gibson <jimsgibson () gmail ! com>
Date: 2012-11-01 15:08:43
Message-ID: 5588D8B9-8E03-475D-AEC1-D9F790A2B872 () gmail ! com
[Download RAW message or body]
On Nov 1, 2012, at 12:44 AM, Thomas Smith wrote:
> Hi,
>
> I'm trying to search a file for several matching blocks of text. A sample
> of what I'm searching through is below.
>
> What I want to do is match "##### START block #####" through to the next
> "##### END block #####" and repeat that throughout the file without
> matching any of the text that falls between each matched block (that is,
> the "ok: some text" lines should not be matched). Here is the one-liner I'm
> using:
>
> perl -p -e '/^##### START block #####.*##### END block #####$/s' file.txt
>
> I've tried a few variations of this but with the same result--a match is
> being made from the first "##### START block #####" to the last "##### END
> block #####", and everything in between... I believe that the ".*",
> combined with the "s" modifier, in the regex is causing this match to be
> made.
The '*' is what's called a "greedy" quantifier. That means it will match as many \
characters in the string as possible. What the regular expression engine does when it \
encounters the pattern '.*' is to immediately match it with as many characters as \
possible. Since your regular expression includes the 's' modifier, this will include \
newlines as well. When the RE engine sees that there are characters in the pattern \
after the '.*', it will start removing characters from the end of the substring \
matched by the '.*' until the subsequent pattern characters are also matched. This \
will continue until there are no characters matched by the '.*'.
The result of all this is that for your pattern, the last '##### END block #####' \
substring is the one that will be matched, and the '.*' pattern will match everything \
between the first '##### START block #####' and the last '##### END block #####'.
The way to fix this is to make the '*' quantifier "non-greedy" by putting a '?' \
quantifier after it. With that pattern, the RE engine will match as few characters as \
possible, and the first START block will pair up with the first subsequent END block. \
A 'g' modifier will tell the RE engine to start looking after each match for the next \
match in the string.
--
To unsubscribe, e-mail: beginners-unsubscribe@perl.org
For additional commands, e-mail: beginners-help@perl.org
http://learn.perl.org/
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic