>>>>> On Mon, 28 May 2001 17:29:40 +0100, "Bornaz, Daniel" <[EMAIL PROTECTED]> 
>said:

Daniel> $stt="The food is under the bar in the barn in the river.";
Daniel> $stt=~/bar(.*?)river/; print "$&";

Daniel> The output is: bar in the barn in the river

Daniel> Instead of the expected: barn in the river

Daniel> guaranteed by the question mark that follows the star. 

You've misunderstood (I think) both the effect of the non-greedy match
modifier ('?') and the way the Perl regex engine works. Perl starts
looking for matches at the left-hand side of the string; once a match
is found, the regex matches. 

In other words, your regex isn't looking for the shortest possible
substring bracketed by 'bar' and 'river'; it's looking for the _first_
possible match bracketed by 'bar' and 'river' (starting at the
left-hand part of the string). Since you've used the non-greedy
operator, Perl tries to extend the match right-ward from the first
'bar' match. If you hadn't used the non-greedy operator, the match
would have back-tracked from the end of the string.

As you note, in this case, that works out to the same thing, but if
your string was 'the food is under the bar in the barn in the river,
down-river from the sandbar', the output _would_ depend on whether the
non-greedy operator was present. (Try it and see!)

AFAIK, the question you're trying to ask (shortest substring between
two other substrings) isn't amenable to regex-ing; I'd probably try to
do something with split(),like this:

--code--
#! /usr/bin/perl -w

use strict;

my $string      = 'The food is under the bar in the barn in the river.';
my $left_bound  = 'bar';
my $right_bound = 'river';
my @matches     = ();

my @one = split /$left_bound/ , $string;
foreach my $one ( @one ) {
  my @two = split /$right_bound/ , $one;
  next if $two[0] eq $one;
  push @matches , $two[0]
}

my $answer = $matches[0];
foreach( 1 .. $#matches ) {
  $answer = $matches[$_] if length( $matches[$_] ) < length( $answer )
}

print "$left_bound$answer$right_bound\n";
--/code--

john.

Reply via email to